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