FatalSignals.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2005-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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     // make sure we're in the right directory
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     // trap-generated signals are automatically redelivered by the OS,
00092     // so we restore the default handler below.
00093     //
00094     // SIGABRT and SIGQUIT, however, need to be redelivered. but, we
00095     // really would like to have stack traces from all threads, so we
00096     // first set a flag indicating that we've started the process,
00097     // then try to deliver the same signal to all the other threads to
00098     // try to get more stack traces
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 } // namespace oasys

Generated on Sat Sep 8 08:36:16 2007 for DTN Reference Implementation by  doxygen 1.5.3