root/siginfo.cpp
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- ckptSignal
- SigInfo_ckptSignal
- setupCkptSigHandler
- saveSigHandlers
- 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 }