00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <dlfcn.h>
00019 #include <signal.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <unistd.h>
00023 #include <pthread.h>
00024
00025 #include "FatalSignals.h"
00026 #include "StackTrace.h"
00027 #include "thread/Thread.h"
00028
00029 namespace oasys {
00030
00031 const char* FatalSignals::appname_ = "(unknown app)";
00032 const char* FatalSignals::core_dir_ = NULL;
00033 bool FatalSignals::in_abort_handler_ = false;
00034
00035 void
00036 FatalSignals::init(const char* appname)
00037 {
00038 appname_ = appname;
00039 signal(SIGSEGV, FatalSignals::handler);
00040 signal(SIGBUS, FatalSignals::handler);
00041 signal(SIGILL, FatalSignals::handler);
00042 signal(SIGFPE, FatalSignals::handler);
00043 signal(SIGABRT, FatalSignals::handler);
00044 signal(SIGQUIT, FatalSignals::handler);
00045 }
00046
00047 void
00048 FatalSignals::cancel()
00049 {
00050 signal(SIGSEGV, SIG_DFL);
00051 signal(SIGBUS, SIG_DFL);
00052 signal(SIGILL, SIG_DFL);
00053 signal(SIGFPE, SIG_DFL);
00054 signal(SIGABRT, SIG_DFL);
00055 signal(SIGQUIT, SIG_DFL);
00056 }
00057
00058 void
00059 FatalSignals::handler(int sig)
00060 {
00061 char* signame = "";
00062 switch(sig) {
00063 #define FATAL(_s) case _s: signame = #_s; break;
00064
00065 FATAL(SIGSEGV);
00066 FATAL(SIGBUS);
00067 FATAL(SIGILL);
00068 FATAL(SIGFPE);
00069 FATAL(SIGABRT);
00070 FATAL(SIGQUIT);
00071
00072 default:
00073 char buf[1024];
00074 snprintf(buf, sizeof(buf), "ERROR: UNEXPECTED FATAL SIGNAL %d\n", sig);
00075 exit(1);
00076 };
00077
00078 fprintf(stderr, "ERROR: %s (pid %d) got fatal %s - will dump core\n",
00079 appname_, (int)getpid(), signame);
00080
00081
00082 if (!in_abort_handler_ && core_dir_ != NULL) {
00083 fprintf(stderr, "fatal handler chdir'ing to core dir '%s'\n",
00084 core_dir_);
00085 chdir(core_dir_);
00086 }
00087
00088 StackTrace::print_current_trace(true);
00089 fflush(stderr);
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 if (sig == SIGABRT || sig == SIGQUIT) {
00100 if (! in_abort_handler_) {
00101 in_abort_handler_ = true;
00102
00103 Thread** ids = Thread::all_threads_;
00104 for (int i = 0; i < Thread::max_live_threads_; ++i) {
00105
00106 if ((ids[i] != NULL) &&
00107 ids[i]->thread_id() != Thread::current())
00108 {
00109 ThreadId_t thread_id = ids[i]->thread_id();
00110 fprintf(stderr,
00111 "fatal handler sending signal to thread %u\n",
00112 (u_int)thread_id);
00113 pthread_kill(thread_id, sig);
00114 sleep(1);
00115 }
00116 }
00117
00118 fprintf(stderr, "fatal handler dumping core\n");
00119 signal(sig, SIG_DFL);
00120 kill(getpid(), sig);
00121 }
00122 } else {
00123 signal(sig, SIG_DFL);
00124 }
00125 }
00126
00127 void
00128 FatalSignals::die()
00129 {
00130 Breaker::break_here();
00131 StackTrace::print_current_trace(false);
00132 if (core_dir_ != NULL) {
00133 fprintf(stderr, "fatal handler chdir'ing to core dir '%s'\n",
00134 core_dir_);
00135 chdir(core_dir_);
00136 }
00137
00138 cancel();
00139 ::abort();
00140 }
00141
00142
00143 }