]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Use waitid instead of waitpid when available.
authorBruno Haible <bruno@clisp.org>
Mon, 3 Nov 2003 20:43:03 +0000 (20:43 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:11:07 +0000 (12:11 +0200)
gettext-tools/ChangeLog
gettext-tools/configure.ac
gettext-tools/lib/ChangeLog
gettext-tools/lib/wait-process.c

index 084500d07a3da147d17f3b03d3bb27dd156d6e01..714018d8bcbbfb56e0e80c185df01e047449bb4e 100644 (file)
@@ -1,3 +1,7 @@
+2003-10-31  Bruno Haible  <bruno@clisp.org>
+
+       * configure.ac: Also check for waitid.
+
 2003-10-31  Bruno Haible  <bruno@clisp.org>
 
        * configure.ac: Remove argument of FIX_MAKEFILE_COMPILE,
index 880e7223add7abfa99030fa2f8e611d6b0e05190..e7e2c7bd2878377af3f8d19771fb829627bd2ff3 100644 (file)
@@ -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
index e7ab59d09eed467b8fb54a8c53835fae48ab83a9..f23bdee58ebe45daddeb7ab7d2b60befc8d6887f 100644 (file)
@@ -1,3 +1,8 @@
+2003-10-31  Bruno Haible  <bruno@clisp.org>
+
+       * wait-process.h (wait_process): Use waitid with WNOWAIT if available,
+       to avoid (extremely rare) race condition.
+
 2003-10-27  Bruno Haible  <bruno@clisp.org>
 
        * stdbool_.h: Better support for BeOS.
index 83f7b39675bd9111c6dcaf75baff98d13bd84f4d..26a889ca48f8bbf8645b555de6872a9b0fd16115 100644 (file)
@@ -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
 }