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