Sierra Toolkit Version of the Day
Signal.cpp
00001 
00010 #include <iostream>
00011 
00012 #include <signal.h>
00013 
00014 #include <stk_util/diag/Env.hpp>
00015 #include <stk_util/diag/Signal.hpp>
00016 #include <stk_util/util/Callback.hpp>
00017 #include <stk_util/util/FeatureTest.hpp>
00018 #include <stk_util/diag/SignalHandler.hpp>
00019 
00020 namespace sierra {
00021 namespace Env {
00022 
00023 namespace {
00024 
00029 class EnvSignal
00030 {
00031 public:
00032   static EnvSignal &instance() {
00033     static EnvSignal env_signal;
00034 
00035     return env_signal;
00036   }
00037 
00038 private:
00039   EnvSignal()
00040     : m_enabled(false),
00041       m_hupReceived(false),
00042       hupCallback(*this, &EnvSignal::hupHandler),
00043       segvCallback(*this, &EnvSignal::segvHandler),
00044       illCallback(*this, &EnvSignal::illHandler),
00045       busCallback(*this, &EnvSignal::busHandler),
00046       termCallback(*this, &EnvSignal::termHandler)
00047   {}
00048 
00049 public:
00065   inline sigjmp_buf *getSigJmpBuf() {
00066     m_enabled = true;
00067 
00068     return &m_sigJmpBuf;
00069   }
00070 
00076   void disableSigLongJmp() {
00077     m_enabled = false;
00078   }
00079 
00087   const std::string &message() const {
00088     return m_message;
00089   }
00090 
00095   bool getHUPReceived() {
00096     return m_hupReceived;
00097   }
00098 
00103   void activateSignals();
00104 
00109   void deactivateSignals();
00110 
00111 private:
00112   void doSignal(const char *message, int signal);
00113   void hupHandler();
00114   void segvHandler();
00115   void illHandler();
00116   void busHandler();
00117   void termHandler();
00118   void intHandler();
00119 
00120 private:
00121   sigjmp_buf    m_sigJmpBuf;      
00122   bool      m_enabled;      
00123   bool      m_hupReceived;      
00124   std::string   m_message;      
00125 
00126   Callback<EnvSignal> hupCallback;
00127   Callback<EnvSignal> segvCallback;
00128   Callback<EnvSignal> illCallback;
00129   Callback<EnvSignal> busCallback;
00130   Callback<EnvSignal> termCallback;
00131 //  Callback<EnvSignal> intCallback;
00132 
00133 };
00134 
00135 
00136   void
00137 EnvSignal::activateSignals()
00138 {
00139   SignalHandler::instance().add_handler(SIGSEGV, EnvSignal::segvCallback);
00140   SignalHandler::instance().add_handler(SIGILL, EnvSignal::illCallback);
00141   SignalHandler::instance().add_handler(SIGBUS, EnvSignal::busCallback);
00142 //   SignalHandler::instance().add_handler(SIGINT, EnvSignal::intCallback);
00143 
00144 #if defined(SIERRA_USER_SHUTDOWN_SIGNAL)
00145   SignalHandler::instance().add_handler(SIERRA_USER_SHUTDOWN_SIGNAL, EnvSignal::hupCallback);
00146 #endif
00147 #if defined(SIERRA_SHUTDOWN_SIGNAL)
00148   SignalHandler::instance().add_handler(SIERRA_SHUTDOWN_SIGNAL, EnvSignal::hupCallback);
00149 #endif
00150 #if defined(SIERRA_MPI_ABORT_SIGNAL)
00151   SignalHandler::instance().add_handler(SIERRA_MPI_ABORT_SIGNAL, EnvSignal::termCallback);
00152 #endif
00153 }
00154 
00155 
00156 void
00157 EnvSignal::deactivateSignals()
00158 {
00159   SignalHandler::instance().remove_handler(SIGSEGV, EnvSignal::segvCallback);
00160   SignalHandler::instance().remove_handler(SIGILL, EnvSignal::illCallback);
00161   SignalHandler::instance().remove_handler(SIGBUS, EnvSignal::busCallback);
00162 //   SignalHandler::instance().add_handler(SIGINT, EnvSignal::intCallback);
00163 
00164 #if defined(SIERRA_USER_SHUTDOWN_SIGNAL)
00165   SignalHandler::instance().remove_handler(SIERRA_USER_SHUTDOWN_SIGNAL, EnvSignal::hupCallback);
00166 #endif
00167 #if defined(SIERRA_SHUTDOWN_SIGNAL)
00168   SignalHandler::instance().remove_handler(SIERRA_SHUTDOWN_SIGNAL, EnvSignal::hupCallback);
00169 #endif
00170 #if defined(SIERRA_MPI_ABORT_SIGNAL)
00171   SignalHandler::instance().remove_handler(SIERRA_MPI_ABORT_SIGNAL, EnvSignal::termCallback);
00172 #endif
00173 }
00174 
00175 
00176 void
00177 EnvSignal::doSignal(
00178   const char *  message,
00179   int   signal)
00180 {
00181   if (!m_enabled) {
00182 //    std::cout << message << std::endl << "Signal exception handling not enabled" << std::endl;
00183     ::raise(signal);
00184     return;
00185   }
00186   else {
00187     m_enabled = false;
00188     m_message = message;
00189     ::siglongjmp(m_sigJmpBuf, signal);
00190   }
00191 }
00192 
00193 
00194 void
00195 EnvSignal::hupHandler()
00196 {
00197   m_hupReceived = true;
00198 }
00199 
00200 
00201 void
00202 EnvSignal::intHandler()
00203 {
00204   m_hupReceived = true;
00205 }
00206 
00207 
00208 void
00209 EnvSignal::segvHandler()
00210 {
00211   SignalHandler::instance().remove_handler(SIGSEGV, EnvSignal::segvCallback);
00212   doSignal("Segmentation violation error", SIGSEGV);
00213 }
00214 
00215 void
00216 EnvSignal::busHandler()
00217 {
00218   SignalHandler::instance().remove_handler(SIGBUS, EnvSignal::busCallback);
00219   doSignal("Bus error", SIGBUS);
00220 }
00221 
00222 
00223 void
00224 EnvSignal::illHandler()
00225 {
00226   SignalHandler::instance().remove_handler(SIGILL, EnvSignal::illCallback);
00227   doSignal("Illegal instruction error", SIGILL);
00228 }
00229 
00230 
00231 void
00232 EnvSignal::termHandler()
00233 {
00234   SignalHandler::instance().remove_handler(SIGTERM, EnvSignal::termCallback);
00235   doSignal("Terminate signal received, likely due to an abort on another processor\n"
00236      "Refer to standard output log for more information", SIGTERM);
00237 }
00238 
00239 } // namespace <unnamed>
00240 
00241 
00242 void
00243 activate_signals()
00244 {
00245   EnvSignal::instance().activateSignals();
00246 }
00247 
00248 
00249 void
00250 deactivate_signals()
00251 {
00252   EnvSignal::instance().deactivateSignals();
00253 }
00254 
00255 
00256 sigjmp_buf *
00257 get_sigjmpbuf()
00258 {
00259   return EnvSignal::instance().getSigJmpBuf();
00260 }
00261 
00262 
00263 void
00264 disable_siglongjmp()
00265 {
00266   return EnvSignal::instance().disableSigLongJmp();
00267 }
00268 
00269 
00270 const std::string &
00271 get_signal_message()
00272 {
00273   return EnvSignal::instance().message();
00274 }
00275 
00276 
00277 bool
00278 HUP_received()
00279 {
00280   return EnvSignal::instance().getHUPReceived();
00281 }
00282 
00283 } // namespace Env
00284 } // namespace sierra
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines