Home | History | Annotate | Line # | Download | only in dist
      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