CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/FWCore/Utilities/src/UnixSignalHandlers.cc

Go to the documentation of this file.
00001 #include <iostream>
00002 #include <iomanip>
00003 #include <cstdlib>
00004 #include <cstdio>
00005 #include <cstring>
00006 
00007 #include "FWCore/Utilities/interface/UnixSignalHandlers.h"
00008 #include "FWCore/Utilities/interface/DebugMacros.h"
00009 
00010 #if !defined(NSIG)
00011 #if defined(_NSIG)
00012 #define NSIG _NSIG
00013 #elif defined(__DARWIN_NSIG)
00014 #define NSIG __DARWIN_NSIG
00015 #endif
00016 #endif
00017 
00018 namespace edm {
00019 
00020     boost::mutex usr2_lock;
00021 
00022 //--------------------------------------------------------------
00023 
00024     volatile bool shutdown_flag = false;
00025 
00026     extern "C" {
00027       void ep_sigusr2(int,siginfo_t*,void*)
00028       {
00029         FDEBUG(1) << "in sigusr2 handler\n";
00030         shutdown_flag = true;
00031       }
00032     }
00033 
00034 //--------------------------------------------------------------
00035 
00036     boost::mutex signum_lock;
00037     volatile int signum_value = 
00038 #if defined(__linux__)
00039       SIGRTMIN;
00040 #else
00041     0;
00042 #endif
00043 
00044 //--------------------------------------------------------------
00045 
00046     int getSigNum()
00047     {
00048       boost::mutex::scoped_lock sl(signum_lock);
00049       int rc = signum_value;
00050       ++signum_value;
00051       return rc;
00052     }
00053 
00054 #define MUST_BE_ZERO(fun) if((fun) != 0)                                        \
00055       { perror("UnixSignalHandlers::setupSignal: sig function failed"); abort(); }
00056 
00057 //--------------------------------------------------------------
00058 
00059     void disableAllSigs( sigset_t* oldset )
00060     {
00061       sigset_t myset;
00062       // all blocked for now
00063       MUST_BE_ZERO(sigfillset(&myset));
00064       MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK,&myset,oldset));
00065     }
00066 
00067 //--------------------------------------------------------------
00068 
00069     void disableRTSigs()
00070     {
00071 #if defined(__linux__)
00072       // ignore all the RT signals
00073       sigset_t myset;
00074       MUST_BE_ZERO(sigemptyset(&myset));
00075       
00076       struct sigaction tmpact;
00077       memset(&tmpact,0,sizeof(tmpact));
00078       tmpact.sa_handler = SIG_IGN;
00079 
00080       for(int num = SIGRTMIN; num < SIGRTMAX; ++num) {
00081           MUST_BE_ZERO(sigaddset(&myset,num));
00082           MUST_BE_ZERO(sigaction(num,&tmpact,NULL));
00083       }
00084       
00085       MUST_BE_ZERO(pthread_sigmask(SIG_BLOCK,&myset,0));
00086 #endif
00087     }
00088 
00089 //--------------------------------------------------------------
00090 
00091     void reenableSigs( sigset_t* oldset )
00092     {
00093       // reenable the signals
00094       MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK,oldset,0));
00095     }
00096 
00097 //--------------------------------------------------------------
00098 
00099     void enableSignal( sigset_t* newset, const int signum )
00100     {
00101       // enable the specified signal
00102       MUST_BE_ZERO(sigaddset(newset, signum));
00103     }
00104 
00105 
00106 //--------------------------------------------------------------
00107 
00108     void disableSignal( sigset_t* newset, const int signum )
00109     {
00110       // disable the specified signal
00111       MUST_BE_ZERO(sigdelset(newset, signum));
00112     }
00113 
00114 //--------------------------------------------------------------
00115 
00116     void installCustomHandler( const int signum, CFUNC func )
00117     {
00118       sigset_t oldset;
00119       edm::disableAllSigs(&oldset);
00120 #if defined(__linux__)
00121       edm::disableRTSigs();
00122 #endif
00123       edm::installSig(signum,func);
00124       edm::reenableSigs(&oldset);
00125     }
00126 
00127 //--------------------------------------------------------------
00128 
00129     void installSig( const int signum, CFUNC func )
00130     {
00131       // set up my RT signal now
00132       struct sigaction act;
00133       memset(&act,0,sizeof(act));
00134       act.sa_sigaction = func;
00135       act.sa_flags = SA_RESTART;
00136       
00137       // get my signal number
00138       int mysig = signum;
00139       if( mysig == SIGKILL ) {
00140         perror("Cannot install handler for KILL signal");
00141         return;
00142       } else if( mysig == SIGSTOP ) {
00143          perror("Cannot install handler for STOP signal");
00144         return;
00145       }
00146       
00147       if(sigaction(mysig,&act,NULL) != 0) {
00148           perror("sigaction failed");
00149           abort();
00150       }
00151       
00152       sigset_t newset;
00153       MUST_BE_ZERO(sigemptyset(&newset));
00154       MUST_BE_ZERO(sigaddset(&newset,mysig));
00155       MUST_BE_ZERO(pthread_sigmask(SIG_UNBLOCK,&newset,0));
00156     }
00157 
00158 //--------------------------------------------------------------
00159 
00160     void sigInventory()
00161     {
00162       sigset_t tmpset, oldset;
00163 //    Make a full house set of signals, except for SIGKILL = 9
00164 //    and SIGSTOP = 19 which cannot be blocked
00165       MUST_BE_ZERO(sigfillset(&tmpset));
00166       MUST_BE_ZERO(sigdelset(&tmpset, SIGKILL));
00167       MUST_BE_ZERO(sigdelset(&tmpset, SIGSTOP));
00168 //    Swap it with the current sigset_t
00169       MUST_BE_ZERO(pthread_sigmask( SIG_SETMASK, &tmpset, &oldset ));
00170 //    Now see what's included in the set
00171       for(int k=1; k<NSIG; ++k) {
00172         std::cerr << "sigismember is " << sigismember( &tmpset, k )
00173                   << " for signal " << std::setw(2) << k
00174 #if defined(__linux__)
00175                   << " (" << strsignal(k) << ")"
00176 #endif
00177                   << std::endl;
00178       }
00179 //    Finally put the original sigset_t back
00180       MUST_BE_ZERO(pthread_sigmask( SIG_SETMASK, &oldset, &tmpset));
00181     }
00182 
00183 } // end of namespace edm