root/siginfo.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ckptSignal
  2. SigInfo_ckptSignal
  3. setupCkptSigHandler
  4. saveSigHandlers
  5. restoreSigHandlers

   1 #include <signal.h>
   2 #include <stdlib.h>
   3 #include <errno.h>
   4 #include <string.h>
   5 #include "constants.h"
   6 #include "dmtcp.h"
   7 #include "syscallwrappers.h"
   8 #include "threadlist.h"
   9 #include "siginfo.h"
  10 #include "jassert.h"
  11 
  12 using namespace dmtcp;
  13 
  14 static int STOPSIGNAL;
  15 /* NOTE:  NSIG == SIGRTMAX+1 == 65 on Linux; NSIG is const, SIGRTMAX isn't */
  16 static struct sigaction sigactions[NSIG];
  17 
  18 int SigInfo::ckptSignal() { return STOPSIGNAL; }
  19 extern "C" int SigInfo_ckptSignal() { return STOPSIGNAL; }
  20 
  21 /*****************************************************************************
  22  *
  23  *  Set the thread's STOPSIGNAL handler.  Threads are sent STOPSIGNAL when they
  24  *  are to suspend execution the application, save their state and wait for the
  25  *  checkpointhread to write the checkpoint file.
  26  *
  27  *    Output:
  28  *
  29  *      Calling thread will call stopthisthread() when sent a STOPSIGNAL
  30  *
  31  *****************************************************************************/
  32 void SigInfo::setupCkptSigHandler(sighandler_t handler)
  33 {
  34   static int init = 0;
  35 
  36   if (!init) {
  37     char *tmp, *endp;
  38     init = 1;
  39     /* If the user has defined a signal, use that to suspend.  Otherwise, use
  40      * CKPT_SIGNAL */
  41     tmp = getenv("DMTCP_SIGCKPT");
  42     if (tmp == NULL) {
  43       STOPSIGNAL = CKPT_SIGNAL;
  44     } else {
  45       errno = 0;
  46       STOPSIGNAL = strtol(tmp, &endp, 0);
  47 
  48       if ((errno != 0) || (tmp == endp)) {
  49         JWARNING(false) (getenv("DMTCP_SIGCKPT")) (CKPT_SIGNAL)
  50           .Text("Your chosen SIGCKPT does not translate to a number, and cannot be"
  51                 "used.  Default signal will be used instead");
  52         STOPSIGNAL = CKPT_SIGNAL;
  53       } else if (STOPSIGNAL < 1 || STOPSIGNAL > 31) {
  54         JNOTE("Your chosen SIGCKPT is not a valid signal, and cannot be used."
  55               " Default signal will be used instead.")
  56           (STOPSIGNAL) (CKPT_SIGNAL);
  57         STOPSIGNAL = CKPT_SIGNAL;
  58       }
  59     }
  60   }
  61 
  62   struct sigaction act, old_act;
  63   memset(&act, 0, sizeof act);
  64   act.sa_handler = handler;
  65   sigfillset(&act.sa_mask);
  66   act.sa_flags = SA_RESTART;
  67 
  68   // We can't use standard sigaction here, because DMTCP has a wrapper around
  69   //  it that will not allow anyone to set a signal handler for SIGUSR2.
  70   JASSERT(_real_sigaction(STOPSIGNAL, &act, &old_act) != -1) (JASSERT_ERRNO)
  71     .Text("Error setting up signal handler");
  72 
  73   if ((old_act.sa_handler != SIG_IGN) && (old_act.sa_handler != SIG_DFL) &&
  74       (old_act.sa_handler != handler)) {
  75     JASSERT(false) (STOPSIGNAL) (old_act.sa_handler)
  76       .Text("\nSignal handler already in use. You may employ a different\n"
  77             "signal by setting the environment variable DMTCP_SIGCKPT to the\n"
  78             "number of the signal that DMTCP should use for checkpointing.\n");
  79   }
  80 }
  81 
  82 /*****************************************************************************
  83  *
  84  *  Save all signal handlers
  85  *
  86  *****************************************************************************/
  87 void SigInfo::saveSigHandlers()
  88 {
  89   int sig;
  90   struct sigaction old_act, act;
  91 
  92   /* Remove STOPSIGNAL from pending signals list:
  93    * Under Ptrace, STOPSIGNAL is sent to the inferior threads once by the
  94    * superior thread and once by the ckpt-thread of the inferior. STOPSIGNAL
  95    * is blocked while the inferior thread is executing the signal handler and
  96    * so the signal is becomes pending and is delivered right after returning
  97    * from stopthisthread.
  98    * To tackle this, we disable/re-enable signal handler for STOPSIGNAL.
  99    */
 100   memset(&act, 0, sizeof act);
 101   act.sa_handler = SIG_IGN;
 102   // Remove signal handler
 103   JASSERT(_real_sigaction(STOPSIGNAL, &act, &old_act) != -1) (JASSERT_ERRNO)
 104     .Text("Error setting up signal handler");
 105   // Reinstall the previous handler
 106   JASSERT(_real_sigaction(STOPSIGNAL, &old_act, NULL) != -1) (JASSERT_ERRNO)
 107     .Text("Error setting up signal handler");
 108 
 109   /* Now save all the signal handlers */
 110   JTRACE("saving signal handlers");
 111   for (sig = SIGRTMAX; sig > 0; --sig) {
 112     if (sigaction (sig, NULL, &sigactions[sig]) < 0) {
 113       JASSERT(errno == EINVAL) (sig) (JASSERT_ERRNO)
 114         .Text("error saving signal action");
 115       memset (&sigactions[sig], 0, sizeof sigactions[sig]);
 116     }
 117 
 118     if (sigactions[sig].sa_handler != SIG_DFL) {
 119       JTRACE("saving signal handler (non-default) for") (sig);
 120     }
 121   }
 122 }
 123 
 124 /*****************************************************************************
 125  *
 126  *  Restore all saved signal handlers
 127  *
 128  *****************************************************************************/
 129 void SigInfo::restoreSigHandlers()
 130 {
 131   int sig;
 132   JTRACE("restoring signal handlers");
 133   for(sig = SIGRTMAX; sig > 0; --sig) {
 134 #ifdef VERBOSE_DEBUG
 135     JTRACE("restore signal handler for") (sig);
 136 #endif
 137 
 138     JASSERT(_real_sigaction(sig, &sigactions[sig], NULL) == 0 || errno == EINVAL)
 139       (sig) (JASSERT_ERRNO)
 140       .Text("error restoring signal handler");
 141   }
 142 }

/* [<][>][^][v][top][bottom][index][help] */