1 /* $Xorg: signals.c,v 1.4 2001/02/09 02:06:01 xorgcvs Exp $ */
2 /******************************************************************************
3
4 Copyright 1994, 1998 The Open Group
5
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25 ******************************************************************************/
26 /* $XFree86: xc/programs/xsm/signals.c,v 3.5 2001/12/08 18:33:45 herrb Exp $ */
27
28 #include <stdlib.h>
29
30 #include <X11/Xos.h>
31 #include <X11/Xfuncs.h>
32 #include <X11/Intrinsic.h>
33
34 #include <X11/SM/SMlib.h>
35
36 #include "save.h"
37
38 #include <errno.h>
39 #ifdef USG
40 #ifndef __TYPES__
41 #include <sys/types.h> /* forgot to protect it... */
42 #define __TYPES__
43 #endif /* __TYPES__ */
44 #else
45 #if defined(_POSIX_SOURCE) && defined(MOTOROLA)
46 #undef _POSIX_SOURCE
47 #include <sys/types.h>
48 #define _POSIX_SOURCE
49 #else
50 #include <sys/types.h>
51 #endif
52 #endif /* USG */
53
54 #ifdef X_POSIX_C_SOURCE
55 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
56 #include <signal.h>
57 #include <sys/wait.h>
58 #undef _POSIX_C_SOURCE
59 #else
60 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
61 #include <signal.h>
62 #include <sys/wait.h>
63 #else
64 #define _POSIX_SOURCE
65 #include <signal.h>
66 #ifdef SCO325
67 #include <sys/procset.h>
68 #include <sys/siginfo.h>
69 #endif
70 #include <sys/wait.h>
71 #undef _POSIX_SOURCE
72 #endif
73 #endif
74 #include "list.h"
75 #include "save.h"
76
77 #ifndef X_NOT_POSIX
78 #define USE_POSIX_WAIT
79 #endif
80
81 #if defined(linux) || defined(SYSV)
82 #define USE_SYSV_SIGNALS
83 #endif
84
85 #if defined(SCO)
86 #undef SIGTSTP /* defined, but not the BSD way */
87 #endif
88
89 #if defined(X_NOT_POSIX) && defined(SYSV)
90 #define SIGNALS_RESET_WHEN_CAUGHT
91 #endif
92
93 #include <stddef.h>
94
95 #include "xsm.h"
96
97 int checkpoint_from_signal = 0;
98
99
100 static void
Signal(int sig,void (* handler)(int))101 Signal(int sig, void (*handler)(int))
102 {
103 #ifndef X_NOT_POSIX
104 struct sigaction sigact, osigact;
105 sigact.sa_handler = handler;
106 sigemptyset(&sigact.sa_mask);
107 sigact.sa_flags = 0;
108 sigaction(sig, &sigact, &osigact);
109 #else
110 signal(sig, handler);
111 #endif
112 }
113
114
115 void
sig_child_handler(int sig)116 sig_child_handler (int sig)
117
118 {
119 int pid, olderrno = errno;
120
121 #if !defined(USE_POSIX_WAIT) && defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
122 wait (NULL);
123 #endif
124
125 #ifdef SIGNALS_RESET_WHEN_CAUGHT
126 Signal (SIGCHLD, sig_child_handler);
127 #endif
128
129 /*
130 * The wait() above must come before re-establishing the signal handler.
131 * In between this time, a new child might have died. If we can do
132 * a non-blocking wait, we can check for this race condition. If we
133 * don't have non-blocking wait, we lose.
134 */
135
136 do
137 {
138 #ifdef USE_POSIX_WAIT
139 pid = waitpid (-1, NULL, WNOHANG);
140 #else
141 #if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
142 /* cannot do non-blocking wait */
143 pid = 0;
144 #else
145 union wait status;
146
147 pid = wait3 (&status, WNOHANG, (struct rusage *)NULL);
148 #endif
149 #endif /* USE_POSIX_WAIT else */
150 }
151 while (pid > 0);
152 errno = olderrno;
153 }
154
155
156 void
sig_term_handler(int sig)157 sig_term_handler(int sig)
158 {
159 XtNoticeSignal(sig_term_id);
160 }
161
162 void
xt_sig_term_handler(XtPointer closure,XtSignalId * id)163 xt_sig_term_handler (XtPointer closure, XtSignalId *id)
164
165 {
166 wantShutdown = 1;
167 checkpoint_from_signal = 1;
168 DoSave (SmSaveLocal, SmInteractStyleNone, 1 /* fast */);
169 }
170
sig_usr1_handler(int sig)171 void sig_usr1_handler(int sig)
172 {
173 XtNoticeSignal(sig_usr1_id);
174 }
175
176 void
xt_sig_usr1_handler(XtPointer closure,XtSignalId * id)177 xt_sig_usr1_handler (XtPointer closure, XtSignalId *id)
178
179 {
180 wantShutdown = 0;
181 checkpoint_from_signal = 1;
182 DoSave (SmSaveLocal, SmInteractStyleNone, 0 /* fast */);
183 }
184
185
186
187 void
register_signals(XtAppContext appContext)188 register_signals (XtAppContext appContext)
189
190 {
191 /*
192 * Ignore SIGPIPE
193 */
194
195 Signal (SIGPIPE, SIG_IGN);
196
197
198 /*
199 * If child process dies, call our handler
200 */
201
202 Signal (SIGCHLD, sig_child_handler);
203
204
205 /*
206 * If we get a SIGTERM, do shutdown, fast, local, no interact
207 */
208
209 Signal (SIGTERM, sig_term_handler);
210 sig_term_id = XtAppAddSignal(appContext, xt_sig_term_handler, NULL);
211
212
213 /*
214 * If we get a SIGUSR1, do checkpoint, local, no interact
215 */
216
217 Signal (SIGUSR1, sig_usr1_handler);
218 sig_usr1_id = XtAppAddSignal(appContext, xt_sig_usr1_handler, NULL);
219 }
220
221
222
223 int
execute_system_command(char * s)224 execute_system_command (char *s)
225 {
226 int stat;
227
228 #ifdef X_NOT_POSIX
229 /*
230 * Non-POSIX system() uses wait(). We must disable our sig child
231 * handler because if it catches the signal, system() will block
232 * forever in wait().
233 */
234
235 int pid;
236
237 Signal (SIGCHLD, SIG_IGN);
238 #endif
239
240 stat = system (s);
241
242 #ifdef X_NOT_POSIX
243 /*
244 * Re-enable our sig child handler. We might have missed some signals,
245 * so do non-blocking waits until there are no signals left.
246 */
247
248 Signal (SIGCHLD, sig_child_handler);
249
250 #if !(defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP))
251 do
252 {
253 union wait status;
254
255 pid = wait3 (&status, WNOHANG, (struct rusage *)NULL);
256 } while (pid > 0);
257 #endif
258 #endif /* X_NOT_POSIX */
259
260 return (stat);
261 }
262
263
264