From: Thomas Jarosch Date: Wed, 18 Oct 2017 16:47:49 +0000 (+0200) Subject: timeout: fix regression when invoked with blocked SIGCHLD X-Git-Tag: v8.29~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cccd01b4dae1061dcad2ae14bea976ed86268d9b;p=thirdparty%2Fcoreutils.git timeout: fix regression when invoked with blocked SIGCHLD 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. --- diff --git a/NEWS b/NEWS index 2878b702d3..c3128e1451 100644 --- 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 diff --git a/src/timeout.c b/src/timeout.c index a58b84f4e1..9be70e0152 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -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