Back to index

im-sdk  12.3.91
IMSignal.cpp
Go to the documentation of this file.
00001 #include <config.h>
00002 #include <sstream>
00003 #include <sys/types.h>
00004 #include <sys/wait.h>
00005 #include <unistd.h>
00006 #ifdef HAVE_SIGNAL
00007 #include <signal.h>
00008 #endif
00009 #include "IMSignal.hh"
00010 #include "IMSvr.hh"
00011 #include "IMLog.hh"
00012 
00013 IMSignal* IMSignal::psinst = NULL;
00014 
00015 /*
00016   handlers
00017  */
00018 
00019 RETSIGTYPE
00020 IMSignal::sighup()
00021 {
00022     psvr->reload();
00023 }
00024 
00025 RETSIGTYPE
00026 IMSignal::term()
00027 {
00028     psvr->terminate();
00029 }
00030 
00031 RETSIGTYPE
00032 IMSignal::segv()
00033 {
00034     _segv(SIGSEGV);
00035 }
00036 
00037 RETSIGTYPE
00038 IMSignal::abrt()
00039 {
00040     _segv(SIGABRT);
00041 }
00042 
00043 RETSIGTYPE
00044 IMSignal::trap()
00045 {
00046     _segv(SIGTRAP);
00047 }
00048 
00049 RETSIGTYPE
00050 IMSignal::fpe()
00051 {
00052     _segv(SIGFPE);
00053 }
00054 
00055 RETSIGTYPE
00056 IMSignal::bus()
00057 {
00058     _segv(SIGBUS);
00059 }
00060 
00061 RETSIGTYPE
00062 IMSignal::_segv(int num)
00063 {
00064     static int in_segv = 0;
00065     pid_t pid;
00066     stringstream s;
00067     string spid, signum;
00068 
00069     s << getpid();
00070     spid = s.str();
00071     s.str("");
00072     s << num;
00073     signum = s.str();
00074 
00075     in_segv++;
00076 
00077     if (in_segv > 1) {
00078        /* avoid the multiple segfaulting */
00079        LOG_CRITICAL("Multiple crashes have occurred.  Give up to storing logs.");
00080        _exit(255);
00081     }
00082 
00083     pid = fork();
00084     if (pid < 0) {
00085        LOG_CRITICAL("Crash has occurred.  Unable to store logs.");
00086        _exit(255);
00087     } else if (pid > 0) {
00088        /* parent */
00089        int status;
00090        pid_t retval;
00091 
00092        retval = waitpid(pid, &status, 0);
00093        LOG_CRITICAL("Crash has occurred.  Please see /var/log/iiim/ or $HOME/.iiim/logs/ for details.");
00094        _exit(255);
00095     } else {
00096        /* child */
00097        int retval;
00098 
00099        retval = execl(SEGVLOGGER,
00100                      SEGVLOGGER,
00101                      spid.c_str(), signum.c_str(), NULL);
00102        if (retval == -1)
00103            LOG_CRITICAL("Unable to run logger program `%s'.", SEGVLOGGER);
00104        _exit(99);
00105     }
00106 
00107     in_segv--;
00108 }
00109 
00110 /*
00111   management functions.
00112  */
00113 
00114 RETSIGTYPE
00115 signal_handler(
00116     int num
00117 )
00118 {
00119     IMSignal *pims = IMSignal::get_instance();
00120     IMSignal_handler ph;
00121 
00122     if (!pims) return;
00123     ph = pims->getfunc(num);
00124     if (!ph) return;
00125     (pims->*ph)();
00126     return;
00127 }
00128 
00129 IMSignal_handler
00130 IMSignal::getfunc(
00131     int num
00132 )
00133 {
00134     IMSignalHandlerMap::iterator i;
00135 
00136     i = hmap.find(num);
00137     if (i == hmap.end()) return NULL;
00138 
00139     return i->second;
00140 }
00141 
00142 void
00143 IMSignal::add(
00144     int num,
00145     IMSignal_handler h
00146 )
00147 {
00148     hmap[num] = h;
00149 #ifdef HAVE_SIGACTION
00150     struct sigaction sa;
00151     memset(&sa, 0, sizeof(sa));
00152     sa.sa_handler = signal_handler;
00153     sa.sa_flags = SA_NOCLDSTOP;
00154 #ifdef SA_RESTART
00155     sa.sa_flags |= SA_RESTART;
00156 #endif
00157     ::sigaction(num, &sa, NULL);
00158 #elif defined(HAVE_SIGNAL)
00159     ::signal(num, signal_handler);
00160 #endif
00161 }
00162 
00163 void
00164 IMSignal::ignore(
00165     int num
00166 )
00167 {
00168     hmap[num] = NULL;
00169 #ifdef HAVE_SIGACTION
00170     struct sigaction sa;
00171     memset(&sa, 0, sizeof(sa));
00172     sa.sa_handler = SIG_IGN;
00173 #ifdef SA_RESTART
00174     sa.sa_flags = SA_RESTART;
00175 #endif
00176     ::sigaction(num, &sa, NULL);
00177 #elif defined(HAVE_SIGNAL)
00178     ::signal(num, SIG_IGN);
00179 #endif
00180 }
00181 
00182 IMSignal::IMSignal(
00183     IMSvr *pimsvr
00184 ) : psvr(pimsvr)
00185 {
00186     add(SIGHUP, &IMSignal::sighup);
00187     add(SIGINT, &IMSignal::term);
00188     add(SIGSEGV, &IMSignal::segv);
00189     add(SIGABRT, &IMSignal::abrt);
00190     add(SIGTRAP, &IMSignal::trap);
00191     add(SIGFPE, &IMSignal::fpe);
00192     add(SIGBUS, &IMSignal::bus);
00193     ignore(SIGPIPE);
00194 }
00195 
00196 IMSignal*
00197 IMSignal::construct(
00198     IMSvr *pimsvr
00199 )
00200 {
00201     if (psinst) return psinst;
00202     psinst = new IMSignal(pimsvr);
00203 
00204     return psinst;
00205 }
00206 
00207 /* Local Variables: */
00208 /* c-file-style: "iiim-project" */
00209 /* End: */