diff options
author | Stephan Krempel <krempel@par-tec.com> | 2013-01-25 02:48:46 +0000 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2013-01-26 02:38:52 +0000 |
commit | f8c0258d4643dbabc461a84d0b940be44a680a9b (patch) | |
tree | a693b5ef23d5314a2aa835f8aea213a828b16530 /src | |
parent | 2238ab574191d30b89a007b760c616efaf9c219c (diff) | |
download | coreutils-f8c0258d4643dbabc461a84d0b940be44a680a9b.tar.xz |
timeout: ensure a blocked SIGALRM from the parent is unblocked
* src/timeout.c (unblock_signal): A new function to unblock a
specified signal, or warn if not possible.
(set_timeout): Ensure SIGALRM is unblocked before we setup the timer.
* tests/misc/timeout-blocked.pl: A new test for the issue.
* tests/local.mk: Reference the new test.
* NEWS: Mention the fix.
Fixes: http://bugs.gnu.org/13535
Diffstat (limited to 'src')
-rw-r--r-- | src/timeout.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/src/timeout.c b/src/timeout.c index b163a0ee8..2ffd2b119 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -102,6 +102,16 @@ static struct option const long_options[] = {NULL, 0, NULL, 0} }; +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")); +} + /* Start the timeout after which we'll receive a SIGALRM. Round DURATION up to the next representable value. Treat out-of-range values as if they were maximal, @@ -110,6 +120,11 @@ static struct option const long_options[] = static void settimeout (double duration) { + + /* We configure timers below so that SIGALRM is sent on expiry. + Therefore ensure we don't inherit a mask blocking SIGALRM. */ + unblock_signal (SIGALRM); + /* timer_settime() provides potentially nanosecond resolution. setitimer() is more portable (to Darwin for example), but only provides microsecond resolution and thus is |