/* * Copyright 2001 Sun Microsystems, Inc. ALL RIGHTS RESERVED * Use of this software is authorized pursuant to the * terms of the license found at * http://developers.sun.com/berkeley_license.html */ #include #include #include #include #include static void handle_crash(int sig) { char buf[128]; printf("Processing signal %d\n", sig); /* generate traceback to stdout and copy to /var/tmp/traceback.txt */ sprintf(buf, "/usr/proc/bin/pstack %d " "|/bin/tee /var/tmp/traceback.txt\n", (int)getpid()); /* undefine LD_PRELOAD to avoid 64-bit problems */ (void)putenv("LD_PRELOAD="); system(buf); /* a file in /var/tmp will survive a reboot but not in /tmp */ printf("A copy of the traceback is stored in /var/tmp/traceback.txt\n"); exit(1); } static int (*sigaction_pointer)(); /* pragma init is SVR4-specific, executes before main() */ #pragma init (install_handlers) static void install_handlers(void) { struct sigaction action; action.sa_handler = handle_crash; if (sigemptyset(&action.sa_mask)) perror("sigemptyset() failure"); /* To avoid being caught in the sigaction interposer below, directly call the real sigaction(2) here */ if(sigaction_pointer == NULL) sigaction_pointer = (int (*)())dlsym(RTLD_NEXT, "sigaction"); if (sigaction_pointer(SIGSEGV, &action, NULL)) perror("Can't set up a signal handler for SIGSEGV"); if (sigaction_pointer(SIGBUS, &action, NULL)) perror("Can't set up a signal handler for SIGBUS"); } /* * Remove application's signal handlers for SIGSEGV and SIGBUS * by interposing on signal(3C), sigset(3C) and sigaction(2) */ /* Simplify prototyping */ typedef void Sigfunc(int); Sigfunc *signal (int sig, Sigfunc *disp) { static Sigfunc * (*func)(); if(func == NULL) func = (Sigfunc *(*)())dlsym(RTLD_NEXT, "signal"); if(sig == SIGSEGV || sig == SIGBUS) return(SIG_DFL); else return (func(sig, disp)); } Sigfunc *sigset (int sig, Sigfunc *disp) { static Sigfunc * (*func)(); if(func == NULL) func = (Sigfunc *(*)())dlsym(RTLD_NEXT, "sigset"); if(sig == SIGSEGV || sig == SIGBUS) return(SIG_DFL); else return (func(sig, disp)); } int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { if(sig == SIGSEGV || sig == SIGBUS) return(0); else return (sigaction_pointer(sig, act, oact)); }