signals.c revision 8108eb18
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) || defined(ISC)
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
101int checkpoint_from_signal = 0;
102
103extern XtSignalId sig_term_id, sig_usr1_id;
104extern Bool wantShutdown;
105
106
107SIGVAL (*Signal (sig, handler))()
108    int sig;
109    SIGVAL (*handler)();
110{
111#ifndef X_NOT_POSIX
112    struct sigaction sigact, osigact;
113    sigact.sa_handler = handler;
114    sigemptyset(&sigact.sa_mask);
115    sigact.sa_flags = 0;
116    sigaction(sig, &sigact, &osigact);
117    return osigact.sa_handler;
118#else
119    return signal(sig, handler);
120#endif
121}
122
123
124void
125sig_child_handler (XtPointer closure, XtSignalId id)
126
127{
128    int pid, olderrno = errno;
129
130#if !defined(USE_POSIX_WAIT) && (defined(USE_SYSV_SIGNALS) && \
131    (defined(CRAY) || !defined(SIGTSTP)))
132    wait (NULL);
133#endif
134
135#ifdef SIGNALS_RESET_WHEN_CAUGHT
136    Signal (SIGCHLD, sig_child_handler);
137#endif
138
139    /*
140     * The wait() above must come before re-establishing the signal handler.
141     * In between this time, a new child might have died.  If we can do
142     * a non-blocking wait, we can check for this race condition.  If we
143     * don't have non-blocking wait, we lose.
144     */
145
146    do
147    {
148#ifdef USE_POSIX_WAIT
149	pid = waitpid (-1, NULL, WNOHANG);
150#else
151#if defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP))
152	/* cannot do non-blocking wait */
153	pid = 0;
154#else
155	union wait status;
156
157	pid = wait3 (&status, WNOHANG, (struct rusage *)NULL);
158#endif
159#endif /* USE_POSIX_WAIT else */
160    }
161    while (pid > 0);
162    errno = olderrno;
163}
164
165
166void
167sig_term_handler(int sig)
168{
169    XtNoticeSignal(sig_term_id);
170}
171
172void
173xt_sig_term_handler (XtPointer closure, XtSignalId *id)
174
175{
176    wantShutdown = 1;
177    checkpoint_from_signal = 1;
178    DoSave (SmSaveLocal, SmInteractStyleNone, 1 /* fast */);
179}
180
181void sig_usr1_handler(int sig)
182{
183    XtNoticeSignal(sig_usr1_id);
184}
185
186void
187xt_sig_usr1_handler (XtPointer closure, XtSignalId *id)
188
189{
190    wantShutdown = 0;
191    checkpoint_from_signal = 1;
192    DoSave (SmSaveLocal, SmInteractStyleNone, 0 /* fast */);
193}
194
195
196
197void
198register_signals (XtAppContext appContext)
199
200{
201    /*
202     * Ignore SIGPIPE
203     */
204
205    Signal (SIGPIPE, SIG_IGN);
206
207
208    /*
209     * If child process dies, call our handler
210     */
211
212    Signal (SIGCHLD, sig_child_handler);
213
214
215    /*
216     * If we get a SIGTERM, do shutdown, fast, local, no interact
217     */
218
219    Signal (SIGTERM, sig_term_handler);
220    sig_term_id = XtAppAddSignal(appContext, xt_sig_term_handler, NULL);
221
222
223    /*
224     * If we get a SIGUSR1, do checkpoint, local, no interact
225     */
226
227    Signal (SIGUSR1, sig_usr1_handler);
228    sig_usr1_id = XtAppAddSignal(appContext, xt_sig_usr1_handler, NULL);
229}
230
231
232
233int
234execute_system_command (s)
235
236char *s;
237
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