]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
timeout: fix regression when invoked with blocked SIGCHLD
authorThomas Jarosch <thomas.jarosch@intra2net.com>
Wed, 18 Oct 2017 16:47:49 +0000 (18:47 +0200)
committerPádraig Brady <P@draigBrady.com>
Tue, 24 Oct 2017 06:09:02 +0000 (23:09 -0700)
We inherit the signal mask from our parent process,
therefore ensure SIGCHLD is not blocked.

If SIGCHLD is blocked, sigsuspend() won't be interrupted
when the child process exits and we hang until the timeout (SIGALRM).

This fixes a regression from commit v8.26-39-g2f69dba

* src/timeout.c (install_sigchld): Ensure SIGCHLD is unblocked.
* NEWS: Mention the issue.

NEWS
src/timeout.c

diff --git a/NEWS b/NEWS
index 2878b702d356dbc0843d9cd433dfb124cbfef99e..c3128e1451084946161176b3c46edb8b7760c95d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   to attempt to hide the original length of the file name.
   [bug introduced in coreutils-8.28]
 
+  timeout will again notice its managed command exiting, even when
+  invoked with blocked CHLD signal.
+  [bug introduced in coreutils-8.27]
+
 ** Build-related
 
   Default man pages are now distributed which are used if perl is
index a58b84f4e166ced02e75e8a78d80c8b0b9bc4a94..9be70e01521d1c073820cfce9c3e044aa0036707 100644 (file)
@@ -323,6 +323,16 @@ parse_duration (const char* str)
   return duration;
 }
 
+static void
+unblock_signal (int sig)
+{
+  sigset_t unblock_set;
+  sigemptyset (&unblock_set);
+  sigaddset (&unblock_set, sig);
+  if (sigprocmask (SIG_UNBLOCK, &unblock_set, NULL) != 0)
+    error (0, errno, _("warning: sigprocmask"));
+}
+
 static void
 install_sigchld (void)
 {
@@ -333,6 +343,10 @@ install_sigchld (void)
                                  more likely to work cleanly.  */
 
   sigaction (SIGCHLD, &sa, NULL);
+
+  /* We inherit the signal mask from our parent process,
+     so ensure SIGCHLD is not blocked. */
+  unblock_signal (SIGCHLD);
 }
 
 static void
@@ -369,16 +383,6 @@ block_cleanup (int sigterm, sigset_t *old_set)
     error (0, errno, _("warning: sigprocmask"));
 }
 
-static void
-unblock_signal (int sig)
-{
-  sigset_t unblock_set;
-  sigemptyset (&unblock_set);
-  sigaddset (&unblock_set, sig);
-  if (sigprocmask (SIG_UNBLOCK, &unblock_set, NULL) != 0)
-    error (0, errno, _("warning: sigprocmask"));
-}
-
 /* Try to disable core dumps for this process.
    Return TRUE if successful, FALSE otherwise.  */
 static bool