18108eb18Smrg/* $Xorg: signals.c,v 1.4 2001/02/09 02:06:01 xorgcvs Exp $ */
28108eb18Smrg/******************************************************************************
38108eb18Smrg
48108eb18SmrgCopyright 1994, 1998  The Open Group
58108eb18Smrg
68108eb18SmrgPermission to use, copy, modify, distribute, and sell this software and its
78108eb18Smrgdocumentation for any purpose is hereby granted without fee, provided that
88108eb18Smrgthe above copyright notice appear in all copies and that both that
98108eb18Smrgcopyright notice and this permission notice appear in supporting
108108eb18Smrgdocumentation.
118108eb18Smrg
128108eb18SmrgThe above copyright notice and this permission notice shall be included in
138108eb18Smrgall copies or substantial portions of the Software.
148108eb18Smrg
158108eb18SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168108eb18SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178108eb18SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
188108eb18SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
198108eb18SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
208108eb18SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
218108eb18Smrg
228108eb18SmrgExcept as contained in this notice, the name of The Open Group shall not be
238108eb18Smrgused in advertising or otherwise to promote the sale, use or other dealings
248108eb18Smrgin this Software without prior written authorization from The Open Group.
258108eb18Smrg******************************************************************************/
268108eb18Smrg/* $XFree86: xc/programs/xsm/signals.c,v 3.5 2001/12/08 18:33:45 herrb Exp $ */
278108eb18Smrg
288108eb18Smrg#include <stdlib.h>
298108eb18Smrg
308108eb18Smrg#include <X11/Xos.h>
318108eb18Smrg#include <X11/Xfuncs.h>
328108eb18Smrg#include <X11/Intrinsic.h>
338108eb18Smrg
348108eb18Smrg#include <X11/SM/SMlib.h>
358108eb18Smrg
368108eb18Smrg#include "save.h"
378108eb18Smrg
388108eb18Smrg#include <errno.h>
398108eb18Smrg#include <sys/types.h>
408108eb18Smrg
418108eb18Smrg#ifdef X_POSIX_C_SOURCE
428108eb18Smrg#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
438108eb18Smrg#include <signal.h>
448108eb18Smrg#include <sys/wait.h>
458108eb18Smrg#undef _POSIX_C_SOURCE
468108eb18Smrg#else
478108eb18Smrg#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
488108eb18Smrg#include <signal.h>
498108eb18Smrg#include <sys/wait.h>
508108eb18Smrg#else
518108eb18Smrg#define _POSIX_SOURCE
528108eb18Smrg#include <signal.h>
538108eb18Smrg#include <sys/wait.h>
548108eb18Smrg#undef _POSIX_SOURCE
558108eb18Smrg#endif
568108eb18Smrg#endif
578108eb18Smrg#include "list.h"
588108eb18Smrg#include "save.h"
598108eb18Smrg
608108eb18Smrg#ifndef X_NOT_POSIX
618108eb18Smrg#define USE_POSIX_WAIT
628108eb18Smrg#endif
638108eb18Smrg
648d1e6323Smrg#ifdef linux
658108eb18Smrg#define USE_SYSV_SIGNALS
668108eb18Smrg#endif
678108eb18Smrg
688108eb18Smrg#include <stddef.h>
698108eb18Smrg
701a650d1eSmrg#include "xsm.h"
718108eb18Smrg
721a650d1eSmrgint checkpoint_from_signal = 0;
738108eb18Smrg
748108eb18Smrg
758a355152Smrgstatic void
768a355152SmrgSignal(int sig, void (*handler)(int))
778108eb18Smrg{
788108eb18Smrg#ifndef X_NOT_POSIX
798108eb18Smrg    struct sigaction sigact, osigact;
808108eb18Smrg    sigact.sa_handler = handler;
818108eb18Smrg    sigemptyset(&sigact.sa_mask);
828108eb18Smrg    sigact.sa_flags = 0;
838108eb18Smrg    sigaction(sig, &sigact, &osigact);
848108eb18Smrg#else
851a650d1eSmrg    signal(sig, handler);
868108eb18Smrg#endif
878108eb18Smrg}
888108eb18Smrg
898108eb18Smrg
908108eb18Smrgvoid
911a650d1eSmrgsig_child_handler (int sig)
928108eb18Smrg
938108eb18Smrg{
948108eb18Smrg    int pid, olderrno = errno;
958108eb18Smrg
968a355152Smrg#if !defined(USE_POSIX_WAIT) && defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
978108eb18Smrg    wait (NULL);
988108eb18Smrg#endif
998108eb18Smrg
1008108eb18Smrg    /*
1018108eb18Smrg     * The wait() above must come before re-establishing the signal handler.
1028108eb18Smrg     * In between this time, a new child might have died.  If we can do
1038108eb18Smrg     * a non-blocking wait, we can check for this race condition.  If we
1048108eb18Smrg     * don't have non-blocking wait, we lose.
1058108eb18Smrg     */
1068108eb18Smrg
1078108eb18Smrg    do
1088108eb18Smrg    {
1098108eb18Smrg#ifdef USE_POSIX_WAIT
1108108eb18Smrg	pid = waitpid (-1, NULL, WNOHANG);
1118108eb18Smrg#else
1128a355152Smrg#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
1138108eb18Smrg	/* cannot do non-blocking wait */
1148108eb18Smrg	pid = 0;
1158108eb18Smrg#else
1168108eb18Smrg	union wait status;
1178108eb18Smrg
1188108eb18Smrg	pid = wait3 (&status, WNOHANG, (struct rusage *)NULL);
1198108eb18Smrg#endif
1208108eb18Smrg#endif /* USE_POSIX_WAIT else */
1218108eb18Smrg    }
1228108eb18Smrg    while (pid > 0);
1238108eb18Smrg    errno = olderrno;
1248108eb18Smrg}
1258108eb18Smrg
1268108eb18Smrg
1278108eb18Smrgvoid
1288108eb18Smrgsig_term_handler(int sig)
1298108eb18Smrg{
1308108eb18Smrg    XtNoticeSignal(sig_term_id);
1318108eb18Smrg}
1328108eb18Smrg
1338108eb18Smrgvoid
1348108eb18Smrgxt_sig_term_handler (XtPointer closure, XtSignalId *id)
1358108eb18Smrg
1368108eb18Smrg{
1378108eb18Smrg    wantShutdown = 1;
1388108eb18Smrg    checkpoint_from_signal = 1;
1398108eb18Smrg    DoSave (SmSaveLocal, SmInteractStyleNone, 1 /* fast */);
1408108eb18Smrg}
1418108eb18Smrg
1428108eb18Smrgvoid sig_usr1_handler(int sig)
1438108eb18Smrg{
1448108eb18Smrg    XtNoticeSignal(sig_usr1_id);
1458108eb18Smrg}
1468108eb18Smrg
1478108eb18Smrgvoid
1488108eb18Smrgxt_sig_usr1_handler (XtPointer closure, XtSignalId *id)
1498108eb18Smrg
1508108eb18Smrg{
1518108eb18Smrg    wantShutdown = 0;
1528108eb18Smrg    checkpoint_from_signal = 1;
1538108eb18Smrg    DoSave (SmSaveLocal, SmInteractStyleNone, 0 /* fast */);
1548108eb18Smrg}
1558108eb18Smrg
1568108eb18Smrg
1578108eb18Smrg
1588108eb18Smrgvoid
1598108eb18Smrgregister_signals (XtAppContext appContext)
1608108eb18Smrg
1618108eb18Smrg{
1628108eb18Smrg    /*
1638108eb18Smrg     * Ignore SIGPIPE
1648108eb18Smrg     */
1658108eb18Smrg
1668108eb18Smrg    Signal (SIGPIPE, SIG_IGN);
1678108eb18Smrg
1688108eb18Smrg
1698108eb18Smrg    /*
1708108eb18Smrg     * If child process dies, call our handler
1718108eb18Smrg     */
1728108eb18Smrg
1738108eb18Smrg    Signal (SIGCHLD, sig_child_handler);
1748108eb18Smrg
1758108eb18Smrg
1768108eb18Smrg    /*
1778108eb18Smrg     * If we get a SIGTERM, do shutdown, fast, local, no interact
1788108eb18Smrg     */
1798108eb18Smrg
1808108eb18Smrg    Signal (SIGTERM, sig_term_handler);
1818108eb18Smrg    sig_term_id = XtAppAddSignal(appContext, xt_sig_term_handler, NULL);
1828108eb18Smrg
1838108eb18Smrg
1848108eb18Smrg    /*
1858108eb18Smrg     * If we get a SIGUSR1, do checkpoint, local, no interact
1868108eb18Smrg     */
1878108eb18Smrg
1888108eb18Smrg    Signal (SIGUSR1, sig_usr1_handler);
1898108eb18Smrg    sig_usr1_id = XtAppAddSignal(appContext, xt_sig_usr1_handler, NULL);
1908108eb18Smrg}
1918108eb18Smrg
1928108eb18Smrg
1938108eb18Smrg
1948108eb18Smrgint
1951a650d1eSmrgexecute_system_command (char *s)
1968108eb18Smrg{
1978108eb18Smrg    int stat;
1988108eb18Smrg
1998108eb18Smrg#ifdef X_NOT_POSIX
2008108eb18Smrg    /*
2018108eb18Smrg     * Non-POSIX system() uses wait().  We must disable our sig child
2028108eb18Smrg     * handler because if it catches the signal, system() will block
2038108eb18Smrg     * forever in wait().
2048108eb18Smrg     */
2058108eb18Smrg
2068108eb18Smrg    int pid;
2078108eb18Smrg
2088108eb18Smrg    Signal (SIGCHLD, SIG_IGN);
2098108eb18Smrg#endif
2108108eb18Smrg
2118108eb18Smrg    stat = system (s);
2128108eb18Smrg
2138108eb18Smrg#ifdef X_NOT_POSIX
2148108eb18Smrg    /*
2158108eb18Smrg     * Re-enable our sig child handler.  We might have missed some signals,
2168108eb18Smrg     * so do non-blocking waits until there are no signals left.
2178108eb18Smrg     */
2188108eb18Smrg
2198108eb18Smrg    Signal (SIGCHLD, sig_child_handler);
2208108eb18Smrg
2218a355152Smrg#if !(defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP))
2228108eb18Smrg    do
2238108eb18Smrg    {
2248108eb18Smrg	union wait status;
2258108eb18Smrg
2268108eb18Smrg	pid = wait3 (&status, WNOHANG, (struct rusage *)NULL);
2278108eb18Smrg    } while (pid > 0);
2288108eb18Smrg#endif
2298108eb18Smrg#endif   /* X_NOT_POSIX */
2308108eb18Smrg
2318108eb18Smrg    return (stat);
2328108eb18Smrg}
2338108eb18Smrg
2348108eb18Smrg
235