00001
00002
00003
00004
00005
00006
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
00019 static void wr(int fd, const char *str)
00020 {
00021 write(fd, str, strlen(str));
00022 }
00023
00024
00025
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
00071
00072
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
00084
00085
00086
00087
00088
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);
00100 else
00101 {
00102 pid = fork();
00103 if (pid < 0)
00104 wvcrash_real(sig, 2);
00105 else if (pid == 0)
00106 {
00107 close(fds[1]);
00108 dup2(fds[0], 0);
00109 fcntl(0, F_SETFD, 0);
00110
00111 execlp("wvcrash", "wvcrash", NULL);
00112
00113
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)
00122 {
00123 close(fds[0]);
00124 wvcrash_real(sig, fds[1]);
00125 }
00126 }
00127
00128
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 }