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#include <sys/types.h> 40 41#ifdef X_POSIX_C_SOURCE 42#define _POSIX_C_SOURCE X_POSIX_C_SOURCE 43#include <signal.h> 44#include <sys/wait.h> 45#undef _POSIX_C_SOURCE 46#else 47#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) 48#include <signal.h> 49#include <sys/wait.h> 50#else 51#define _POSIX_SOURCE 52#include <signal.h> 53#include <sys/wait.h> 54#undef _POSIX_SOURCE 55#endif 56#endif 57#include "list.h" 58#include "save.h" 59 60#ifndef X_NOT_POSIX 61#define USE_POSIX_WAIT 62#endif 63 64#ifdef linux 65#define USE_SYSV_SIGNALS 66#endif 67 68#include <stddef.h> 69 70#include "xsm.h" 71 72int checkpoint_from_signal = 0; 73 74 75static void 76Signal(int sig, void (*handler)(int)) 77{ 78#ifndef X_NOT_POSIX 79 struct sigaction sigact, osigact; 80 sigact.sa_handler = handler; 81 sigemptyset(&sigact.sa_mask); 82 sigact.sa_flags = 0; 83 sigaction(sig, &sigact, &osigact); 84#else 85 signal(sig, handler); 86#endif 87} 88 89 90void 91sig_child_handler (int sig) 92 93{ 94 int pid, olderrno = errno; 95 96#if !defined(USE_POSIX_WAIT) && defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) 97 wait (NULL); 98#endif 99 100 /* 101 * The wait() above must come before re-establishing the signal handler. 102 * In between this time, a new child might have died. If we can do 103 * a non-blocking wait, we can check for this race condition. If we 104 * don't have non-blocking wait, we lose. 105 */ 106 107 do 108 { 109#ifdef USE_POSIX_WAIT 110 pid = waitpid (-1, NULL, WNOHANG); 111#else 112#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) 113 /* cannot do non-blocking wait */ 114 pid = 0; 115#else 116 union wait status; 117 118 pid = wait3 (&status, WNOHANG, (struct rusage *)NULL); 119#endif 120#endif /* USE_POSIX_WAIT else */ 121 } 122 while (pid > 0); 123 errno = olderrno; 124} 125 126 127void 128sig_term_handler(int sig) 129{ 130 XtNoticeSignal(sig_term_id); 131} 132 133void 134xt_sig_term_handler (XtPointer closure, XtSignalId *id) 135 136{ 137 wantShutdown = 1; 138 checkpoint_from_signal = 1; 139 DoSave (SmSaveLocal, SmInteractStyleNone, 1 /* fast */); 140} 141 142void sig_usr1_handler(int sig) 143{ 144 XtNoticeSignal(sig_usr1_id); 145} 146 147void 148xt_sig_usr1_handler (XtPointer closure, XtSignalId *id) 149 150{ 151 wantShutdown = 0; 152 checkpoint_from_signal = 1; 153 DoSave (SmSaveLocal, SmInteractStyleNone, 0 /* fast */); 154} 155 156 157 158void 159register_signals (XtAppContext appContext) 160 161{ 162 /* 163 * Ignore SIGPIPE 164 */ 165 166 Signal (SIGPIPE, SIG_IGN); 167 168 169 /* 170 * If child process dies, call our handler 171 */ 172 173 Signal (SIGCHLD, sig_child_handler); 174 175 176 /* 177 * If we get a SIGTERM, do shutdown, fast, local, no interact 178 */ 179 180 Signal (SIGTERM, sig_term_handler); 181 sig_term_id = XtAppAddSignal(appContext, xt_sig_term_handler, NULL); 182 183 184 /* 185 * If we get a SIGUSR1, do checkpoint, local, no interact 186 */ 187 188 Signal (SIGUSR1, sig_usr1_handler); 189 sig_usr1_id = XtAppAddSignal(appContext, xt_sig_usr1_handler, NULL); 190} 191 192 193 194int 195execute_system_command (char *s) 196{ 197 int stat; 198 199#ifdef X_NOT_POSIX 200 /* 201 * Non-POSIX system() uses wait(). We must disable our sig child 202 * handler because if it catches the signal, system() will block 203 * forever in wait(). 204 */ 205 206 int pid; 207 208 Signal (SIGCHLD, SIG_IGN); 209#endif 210 211 stat = system (s); 212 213#ifdef X_NOT_POSIX 214 /* 215 * Re-enable our sig child handler. We might have missed some signals, 216 * so do non-blocking waits until there are no signals left. 217 */ 218 219 Signal (SIGCHLD, sig_child_handler); 220 221#if !(defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)) 222 do 223 { 224 union wait status; 225 226 pid = wait3 (&status, WNOHANG, (struct rusage *)NULL); 227 } while (pid > 0); 228#endif 229#endif /* X_NOT_POSIX */ 230 231 return (stat); 232} 233 234 235