Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

wvcrash.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * Routines to generate a stack backtrace automatically when a program
00006  * crashes.
00007  */
00008 #include "wvcrash.h"
00009 #include <signal.h>
00010 #include <execinfo.h>
00011 #include <fcntl.h>
00012 #include <string.h>
00013 #include <unistd.h>
00014 #include <string.h>
00015 
00016 static const char *argv0 = "UNKNOWN";
00017 
00018 // write a string 'str' to fd
00019 static void wr(int fd, const char *str)
00020 {
00021     write(fd, str, strlen(str));
00022 }
00023 
00024 
00025 // convert 'num' to a string and write it to fd.
00026 static void wrn(int fd, int num)
00027 {
00028     int tmp;
00029     char c;
00030     
00031     if (num < 0)
00032     {
00033         wr(fd, "-");
00034         num = -num;
00035     } 
00036     else if (num == 0)
00037     {
00038         wr(fd, "0");
00039         return;
00040     }
00041     
00042     tmp = 0;
00043     while (num > 0)
00044     {
00045         tmp *= 10;
00046         tmp += num%10;
00047         num /= 10;
00048     }
00049     
00050     while (tmp > 0)
00051     {
00052         c = '0' + (tmp%10);
00053         write(fd, &c, 1);
00054         tmp /= 10;
00055     }
00056 }
00057 
00058 
00059 static void wvcrash_real(int sig, int fd)
00060 {
00061     static void *trace[64];
00062     
00063     wr(fd, argv0);
00064     wr(fd, " dying on signal ");
00065     wrn(fd, sig);
00066     wr(fd, "\n\nBacktrace:\n");
00067     backtrace_symbols_fd(trace,
00068                  backtrace(trace, sizeof(trace)/sizeof(trace[0])), fd);
00069     
00070     // we want to create a coredump, and the kernel seems to not want to do
00071     // that if we send ourselves the same signal that we're already in.
00072     // Whatever... just send a different one :)
00073     if (sig == SIGSEGV)
00074         sig = SIGBUS;
00075     else
00076         sig = SIGSEGV;
00077     
00078     signal(sig, SIG_DFL);
00079     kill(getpid(), sig);
00080 }
00081 
00082 
00083 // Hint: we can't do anything really difficult here, because the program is
00084 // probably really confused.  So we should try to limit this to straight
00085 // kernel syscalls (ie. don't fiddle with FILE* or streams or lists, just
00086 // use straight file descriptors.)
00087 // 
00088 // We fork a subprogram to do the fancy stuff like sending email.
00089 // 
00090 void wvcrash(int sig)
00091 {
00092     int fds[2];
00093     pid_t pid;
00094     
00095     signal(sig, SIG_DFL);
00096     wr(2, "\n\nwvcrash: crashing!\n");
00097     
00098     if (pipe(fds))
00099         wvcrash_real(sig, 2); // just use stderr instead
00100     else
00101     {
00102         pid = fork();
00103         if (pid < 0)
00104             wvcrash_real(sig, 2); // just use stderr instead
00105         else if (pid == 0) // child
00106         {
00107             close(fds[1]);
00108             dup2(fds[0], 0); // make stdin read from pipe
00109             fcntl(0, F_SETFD, 0);
00110             
00111             execlp("wvcrash", "wvcrash", NULL);
00112             
00113             // if we get here, we couldn't exec wvcrash
00114             wr(2, "wvcrash: can't exec wvcrash binary "
00115                "- writing to wvcrash.txt!\n");
00116             execlp("dd", "dd", "of=wvcrash.txt", NULL);
00117             
00118             wr(2, "wvcrash: can't exec dd to write to wvcrash.txt!\n");
00119             _exit(127);
00120         }
00121         else if (pid > 0) // parent
00122         {
00123             close(fds[0]);
00124             wvcrash_real(sig, fds[1]);
00125         }
00126     }
00127     
00128     // child (usually)
00129     _exit(126);
00130 }
00131 
00132 
00133 void wvcrash_setup(const char *_argv0)
00134 {
00135     argv0 = _argv0;
00136     signal(SIGSEGV, wvcrash);
00137     signal(SIGBUS,  wvcrash);
00138     signal(SIGABRT, wvcrash);
00139 }

Generated on Sat Aug 24 21:09:33 2002 for WvStreams by doxygen1.2.15