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