]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
timeout: handle multiple children on solaris
authorPádraig Brady <P@draigBrady.com>
Fri, 3 Mar 2017 08:30:20 +0000 (00:30 -0800)
committerPádraig Brady <P@draigBrady.com>
Fri, 3 Mar 2017 08:30:20 +0000 (00:30 -0800)
* src/timeout.c (install_sigchld): A new function to
install the SIGCHLD handler using sigaction() rather
than signal(), because with the latter on solaris
the signal handler is reset to default and thus
sigsuspend() only returns for the first finished child.
Reported by Assaf Gordon.

src/timeout.c

index 6fe0542b7001518ea5549f06c21774e0d60d4c8a..2f1ec645b328a131eaf376e78642b43a33a4c292 100644 (file)
@@ -323,6 +323,18 @@ parse_duration (const char* str)
   return duration;
 }
 
+static void
+install_sigchld (void)
+{
+  struct sigaction sa;
+  sigemptyset (&sa.sa_mask);  /* Allow concurrent calls to handler */
+  sa.sa_handler = chld;
+  sa.sa_flags = SA_RESTART;   /* Restart syscalls if possible, as that's
+                                 more likely to work cleanly.  */
+
+  sigaction (SIGCHLD, &sa, NULL);
+}
+
 static void
 install_cleanup (int sigterm)
 {
@@ -457,7 +469,7 @@ main (int argc, char **argv)
   install_cleanup (term_signal);
   signal (SIGTTIN, SIG_IGN);   /* Don't stop if background child needs tty.  */
   signal (SIGTTOU, SIG_IGN);   /* Don't stop if background child needs tty.  */
-  signal (SIGCHLD, chld);      /* Interrupt sigsuspend() when child exits.   */
+  install_sigchld ();          /* Interrupt sigsuspend() when child exits.   */
 
   monitored_pid = fork ();
   if (monitored_pid == -1)