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