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