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