FatalSignals.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2005 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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     // make sure we're in the right directory
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     // trap-generated signals are automatically redelivered by the OS,
00113     // so we restore the default handler below.
00114     //
00115     // SIGABRT and SIGQUIT, however, need to be redelivered. but, we
00116     // really would like to have stack traces from all threads, so we
00117     // first set a flag indicating that we've started the process,
00118     // then try to deliver the same signal to all the other threads to
00119     // try to get more stack traces
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 } // namespace oasys

Generated on Fri Dec 22 14:47:59 2006 for DTN Reference Implementation by  doxygen 1.5.1