From: Bruno Haible Date: Mon, 3 Nov 2003 20:43:03 +0000 (+0000) Subject: Use waitid instead of waitpid when available. X-Git-Tag: v0.13~175 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=830b1da32d335a967e6f796db02644dea27a8cff;p=thirdparty%2Fgettext.git Use waitid instead of waitpid when available. --- diff --git a/gettext-tools/ChangeLog b/gettext-tools/ChangeLog index 084500d07..714018d8b 100644 --- a/gettext-tools/ChangeLog +++ b/gettext-tools/ChangeLog @@ -1,3 +1,7 @@ +2003-10-31 Bruno Haible + + * configure.ac: Also check for waitid. + 2003-10-31 Bruno Haible * configure.ac: Remove argument of FIX_MAKEFILE_COMPILE, diff --git a/gettext-tools/configure.ac b/gettext-tools/configure.ac index 880e7223a..e7e2c7bd2 100644 --- a/gettext-tools/configure.ac +++ b/gettext-tools/configure.ac @@ -102,7 +102,7 @@ dnl Checks for library functions. gl_FUNC_ALLOCA AC_FUNC_VPRINTF AC_CHECK_FUNCS([chown getcwd posix_spawn raise select strerror strtoul uname \ -utime utimes]) +utime utimes waitid]) AC_REPLACE_FUNCS([atexit memmove memset stpcpy strcspn \ strcasecmp strncasecmp strpbrk strstr vasprintf]) AM_FUNC_GETLINE diff --git a/gettext-tools/lib/ChangeLog b/gettext-tools/lib/ChangeLog index e7ab59d09..f23bdee58 100644 --- a/gettext-tools/lib/ChangeLog +++ b/gettext-tools/lib/ChangeLog @@ -1,3 +1,8 @@ +2003-10-31 Bruno Haible + + * wait-process.h (wait_process): Use waitid with WNOWAIT if available, + to avoid (extremely rare) race condition. + 2003-10-27 Bruno Haible * stdbool_.h: Better support for BeOS. diff --git a/gettext-tools/lib/wait-process.c b/gettext-tools/lib/wait-process.c index 83f7b3967..26a889ca4 100644 --- a/gettext-tools/lib/wait-process.c +++ b/gettext-tools/lib/wait-process.c @@ -252,6 +252,85 @@ wait_subprocess (pid_t child, const char *progname, bool null_stderr, bool slave_process, bool exit_on_error) { +#if HAVE_WAITID && defined WNOWAIT + /* 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 + meanwhile another process acquires the same PID as child, and then - still + before unregister_slave_subprocess() - this process gets a fatal signal, + it would kill the other totally unrelated process. */ + siginfo_t info; + for (;;) + { + if (waitid (P_PID, child, &info, slave_process ? WNOWAIT : 0) < 0) + { +# ifdef EINTR + if (errno == EINTR) + continue; +# endif + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, errno, + _("%s subprocess"), progname); + return 127; + } + + /* info.si_code is set to one of CLD_EXITED, CLD_KILLED, CLD_DUMPED, + CLD_TRAPPED, CLD_STOPPED, CLD_CONTINUED. Loop until the program + terminates. */ + if (info.si_code == CLD_EXITED + || info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) + break; + } + + /* The child process has exited or was signalled. */ + + if (slave_process) + { + /* Unregister the child from the list of slave subprocesses, so that + later, when we exit, we don't kill a totally unrelated process which + may have acquired the same pid. */ + unregister_slave_subprocess (child); + + /* Now remove the zombie from the process list. */ + for (;;) + { + if (waitid (P_PID, child, &info, 0) < 0) + { +# ifdef EINTR + if (errno == EINTR) + continue; +# endif + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, errno, + _("%s subprocess"), progname); + return 127; + } + break; + } + } + + switch (info.si_code) + { + case CLD_KILLED: + case CLD_DUMPED: + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, 0, + _("%s subprocess got fatal signal %d"), + progname, info.si_status); + return 127; + case CLD_EXITED: + if (info.si_status == 127) + { + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, 0, + _("%s subprocess failed"), progname); + return 127; + } + return info.si_status; + default: + abort (); + } +#else /* waitpid() is just as portable as wait() nowadays. */ WAIT_T status; @@ -262,11 +341,11 @@ wait_subprocess (pid_t child, const char *progname, if (result != child) { -#ifdef EINTR +# ifdef EINTR if (errno == EINTR) continue; -#endif -#if 0 /* defined ECHILD */ +# endif +# if 0 /* defined ECHILD */ if (errno == ECHILD) { /* Child process nonexistent?! Assume it terminated @@ -274,7 +353,7 @@ wait_subprocess (pid_t child, const char *progname, *(int *) &status = 0; break; } -#endif +# endif if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, errno, _("%s subprocess"), progname); @@ -311,4 +390,5 @@ wait_subprocess (pid_t child, const char *progname, return 127; } return WEXITSTATUS (status); +#endif }