X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fwait-process.c;h=7db25e995de03bc73478dc3f57253babdc70a474;hb=97020df1c106f5f06f2e06ca4d27c7c7dd878087;hp=26a889ca48f8bbf8645b555de6872a9b0fd16115;hpb=426c2287c6a67def5dfad71e79c08486fac15275;p=gnulib.git diff --git a/lib/wait-process.c b/lib/wait-process.c index 26a889ca4..7db25e995 100644 --- a/lib/wait-process.c +++ b/lib/wait-process.c @@ -1,11 +1,11 @@ /* Waiting for a subprocess to finish. - Copyright (C) 2001-2003 Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005-2008 Free Software Foundation, Inc. Written by Bruno Haible , 2001. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,13 +13,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include /* Specification. */ #include "wait-process.h" @@ -30,68 +27,9 @@ #include #include - -#if defined _MSC_VER || defined __MINGW32__ - -/* Native Woe32 API. */ -#include -#define waitpid(pid,statusp,options) _cwait (statusp, pid, WAIT_CHILD) -#define WAIT_T int -#define WTERMSIG(x) ((x) & 0xff) /* or: SIGABRT ?? */ -#define WCOREDUMP(x) 0 -#define WEXITSTATUS(x) (((x) >> 8) & 0xff) /* or: (x) ?? */ -#define WIFSIGNALED(x) (WTERMSIG (x) != 0) /* or: ((x) == 3) ?? */ -#define WIFEXITED(x) (WTERMSIG (x) == 0) /* or: ((x) != 3) ?? */ -#define WIFSTOPPED(x) 0 - -#else - -/* Unix API. */ #include -/* On Linux, WEXITSTATUS are bits 15..8 and WTERMSIG are bits 7..0, while - BeOS uses the contrary. Therefore we use the abstract macros. */ -#if HAVE_UNION_WAIT -# define WAIT_T union wait -# ifndef WTERMSIG -# define WTERMSIG(x) ((x).w_termsig) -# endif -# ifndef WCOREDUMP -# define WCOREDUMP(x) ((x).w_coredump) -# endif -# ifndef WEXITSTATUS -# define WEXITSTATUS(x) ((x).w_retcode) -# endif -#else -# define WAIT_T int -# ifndef WTERMSIG -# define WTERMSIG(x) ((x) & 0x7f) -# endif -# ifndef WCOREDUMP -# define WCOREDUMP(x) ((x) & 0x80) -# endif -# ifndef WEXITSTATUS -# define WEXITSTATUS(x) (((x) >> 8) & 0xff) -# endif -#endif -/* For valid x, exactly one of WIFSIGNALED(x), WIFEXITED(x), WIFSTOPPED(x) - is true. */ -#ifndef WIFSIGNALED -# define WIFSIGNALED(x) (WTERMSIG (x) != 0 && WTERMSIG(x) != 0x7f) -#endif -#ifndef WIFEXITED -# define WIFEXITED(x) (WTERMSIG (x) == 0) -#endif -#ifndef WIFSTOPPED -# define WIFSTOPPED(x) (WTERMSIG (x) == 0x7f) -#endif -/* Note that portable applications may access - WTERMSIG(x) only if WIFSIGNALED(x) is true, and - WEXITSTATUS(x) only if WIFEXITED(x) is true. */ - -#endif #include "error.h" -#include "exit.h" #include "fatal-signal.h" #include "xalloc.h" #include "gettext.h" @@ -103,6 +41,9 @@ #if defined _MSC_VER || defined __MINGW32__ +#define WIN32_LEAN_AND_MEAN +#include + /* The return value of spawnvp() is really a process handle as returned by CreateProcess(). Therefore we can kill it using TerminateProcess. */ #define kill(pid,sig) TerminateProcess ((HANDLE) (pid), sig) @@ -140,7 +81,7 @@ static size_t slaves_allocated = SIZEOF (static_slaves); /* The cleanup action. It gets called asynchronously. */ static void -cleanup_slaves () +cleanup_slaves (void) { for (;;) { @@ -202,6 +143,7 @@ register_slave_subprocess (pid_t child) slaves_entry_t *old_slaves = slaves; size_t new_slaves_allocated = 2 * slaves_allocated; slaves_entry_t *new_slaves = + (slaves_entry_t *) malloc (new_slaves_allocated * sizeof (slaves_entry_t)); if (new_slaves == NULL) { @@ -249,10 +191,14 @@ unregister_slave_subprocess (pid_t child) return 127. */ int wait_subprocess (pid_t child, const char *progname, - bool null_stderr, - bool slave_process, bool exit_on_error) + bool ignore_sigpipe, bool null_stderr, + bool slave_process, bool exit_on_error, + int *termsigp) { -#if HAVE_WAITID && defined WNOWAIT +#if HAVE_WAITID && defined WNOWAIT && 0 + /* Commented out because waitid() without WEXITED and with WNOWAIT doesn't + work: On Solaris 7 and OSF/1 4.0, it returns -1 and sets errno = ECHILD, + and on HP-UX 10.20 it just hangs. */ /* Use of waitid() with WNOWAIT avoids a race condition: If slave_process is true, and this process sleeps a very long time between the return from waitpid() and the execution of unregister_slave_subprocess(), and @@ -260,9 +206,13 @@ wait_subprocess (pid_t child, const char *progname, before unregister_slave_subprocess() - this process gets a fatal signal, it would kill the other totally unrelated process. */ siginfo_t info; + + if (termsigp != NULL) + *termsigp = 0; for (;;) { - if (waitid (P_PID, child, &info, slave_process ? WNOWAIT : 0) < 0) + if (waitid (P_PID, child, &info, WEXITED | (slave_process ? WNOWAIT : 0)) + < 0) { # ifdef EINTR if (errno == EINTR) @@ -294,7 +244,7 @@ wait_subprocess (pid_t child, const char *progname, /* Now remove the zombie from the process list. */ for (;;) { - if (waitid (P_PID, child, &info, 0) < 0) + if (waitid (P_PID, child, &info, WEXITED) < 0) { # ifdef EINTR if (errno == EINTR) @@ -313,6 +263,12 @@ wait_subprocess (pid_t child, const char *progname, { case CLD_KILLED: case CLD_DUMPED: + if (termsigp != NULL) + *termsigp = info.si_status; /* TODO: or info.si_signo? */ +# ifdef SIGPIPE + if (info.si_status == SIGPIPE && ignore_sigpipe) + return 0; +# endif if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, 0, _("%s subprocess got fatal signal %d"), @@ -332,8 +288,10 @@ wait_subprocess (pid_t child, const char *progname, } #else /* waitpid() is just as portable as wait() nowadays. */ - WAIT_T status; + int status; + if (termsigp != NULL) + *termsigp = 0; *(int *) &status = 0; for (;;) { @@ -361,7 +319,8 @@ wait_subprocess (pid_t child, const char *progname, } /* One of WIFSIGNALED (status), WIFEXITED (status), WIFSTOPPED (status) - must always be true. Loop until the program terminates. */ + must always be true, since we did not specify WCONTINUED in the + waitpid() call. Loop until the program terminates. */ if (!WIFSTOPPED (status)) break; } @@ -376,12 +335,20 @@ wait_subprocess (pid_t child, const char *progname, if (WIFSIGNALED (status)) { + if (termsigp != NULL) + *termsigp = WTERMSIG (status); +# ifdef SIGPIPE + if (WTERMSIG (status) == SIGPIPE && ignore_sigpipe) + return 0; +# endif if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, 0, _("%s subprocess got fatal signal %d"), progname, (int) WTERMSIG (status)); return 127; } + if (!WIFEXITED (status)) + abort (); if (WEXITSTATUS (status) == 127) { if (exit_on_error || !null_stderr)