From fff4ecc82f2bcfa7427596e7ad9c3769fcab040b Mon Sep 17 00:00:00 2001 From: Perberos Date: Fri, 4 Nov 2011 22:16:15 -0300 Subject: first commit --- src/subprocs.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/subprocs.c (limited to 'src/subprocs.c') diff --git a/src/subprocs.c b/src/subprocs.c new file mode 100644 index 0000000..757daf8 --- /dev/null +++ b/src/subprocs.c @@ -0,0 +1,166 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * subprocs.c --- choosing, spawning, and killing screenhacks. + * + * xscreensaver, Copyright (c) 1991-2003 Jamie Zawinski + * Modified: Copyright (c) 2004 William Jon McCann + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#include "config.h" + +#include +#include +#include +#include + +#ifndef ESRCH +# include +#endif + +#include /* sys/resource.h needs this for timeval */ +# include /* for waitpid() and associated macros */ + +#ifdef VMS +# include +# include /* for close */ +# include /* for getpid */ +# define pid_t int +# define fork vfork +#endif /* VMS */ + +#include /* for the signal names */ + +#include +#include "subprocs.h" + +#if !defined(SIGCHLD) && defined(SIGCLD) +# define SIGCHLD SIGCLD +#endif + +/* Semaphore to temporarily turn the SIGCHLD handler into a no-op. + Don't alter this directly -- use block_sigchld() / unblock_sigchld(). +*/ +static int block_sigchld_handler = 0; + + +#ifdef HAVE_SIGACTION +sigset_t +#else /* !HAVE_SIGACTION */ +int +#endif /* !HAVE_SIGACTION */ +block_sigchld (void) +{ +#ifdef HAVE_SIGACTION + sigset_t child_set; + sigemptyset (&child_set); + sigaddset (&child_set, SIGCHLD); + sigaddset (&child_set, SIGPIPE); + sigprocmask (SIG_BLOCK, &child_set, 0); +#endif /* HAVE_SIGACTION */ + + block_sigchld_handler++; + +#ifdef HAVE_SIGACTION + return child_set; +#else /* !HAVE_SIGACTION */ + return 0; +#endif /* !HAVE_SIGACTION */ +} + +void +unblock_sigchld (void) +{ +#ifdef HAVE_SIGACTION + sigset_t child_set; + sigemptyset (&child_set); + sigaddset (&child_set, SIGCHLD); + sigaddset (&child_set, SIGPIPE); + sigprocmask (SIG_UNBLOCK, &child_set, 0); +#endif /* HAVE_SIGACTION */ + + block_sigchld_handler--; +} + +int +signal_pid (int pid, + int signal) +{ + int status = -1; + gboolean verbose = TRUE; + + if (block_sigchld_handler) + /* This function should not be called from the signal handler. */ + abort(); + + block_sigchld (); /* we control the horizontal... */ + + status = kill (pid, signal); + + if (verbose && status < 0) + { + if (errno == ESRCH) + g_message ("Child process %lu was already dead.", + (unsigned long) pid); + else + { + char buf [1024]; + snprintf (buf, sizeof (buf), "Couldn't kill child process %lu", + (unsigned long) pid); + perror (buf); + } + } + + unblock_sigchld (); + + if (block_sigchld_handler < 0) + abort (); + + return status; +} + +#ifndef VMS + +void +await_dying_children (int pid, + gboolean debug) +{ + while (1) + { + int wait_status = 0; + pid_t kid; + + errno = 0; + kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED); + + if (debug) + { + if (kid < 0 && errno) + g_message ("waitpid(%d) ==> %ld (%d)", pid, (long) kid, errno); + else if (kid != 0) + g_message ("waitpid(%d) ==> %ld", pid, (long) kid); + } + + /* 0 means no more children to reap. + -1 means error -- except "interrupted system call" isn't a "real" + error, so if we get that, we should just try again. */ + if (kid < 0 && errno != EINTR) + break; + } +} + + +#else /* VMS */ +static void await_dying_children (saver_info *si) +{ + return; +} +#endif /* VMS */ + -- cgit v1.2.1