summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--src/timeout.c20
2 files changed, 17 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 5d3ca404d..140e6faca 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,12 @@ GNU coreutils NEWS -*- outline -*-
more than PATH_MAX / 3 components. Also affected due to their use
of canonicalize_* functions: df, stat, readlink.
+** Changes in behavior
+
+ timeout now only processes the first signal received from the set
+ it is handling (SIGTERM, SIGINT, ...). This is to support systems that
+ implicitly create threads for some timer functions (like GNU/kFreeBSD).
+
* Noteworthy changes in release 8.13 (2011-09-08) [stable]
diff --git a/src/timeout.c b/src/timeout.c
index d734e4e81..59b937e7c 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -77,7 +77,6 @@
static int timed_out;
static int term_signal = SIGTERM; /* same default as kill command. */
static int monitored_pid;
-static int sigs_to_ignore[NSIG]; /* so monitor can ignore sigs it resends. */
static double kill_after;
static bool foreground; /* whether to use another program group. */
@@ -141,12 +140,20 @@ settimeout (double duration)
alarm (timeint);
}
-/* send sig to group but not ourselves.
- * FIXME: Is there a better way to achieve this? */
+/* send SIG avoiding the current process. */
+
static int
send_sig (int where, int sig)
{
- sigs_to_ignore[sig] = 1;
+ /* If sending to the group, then ignore the signal,
+ so we don't go into a signal loop. Note that this will ignore any of the
+ signals registered in install_signal_handlers(), that are sent after we
+ propagate the first one, which hopefully won't be an issue. Note this
+ process can be implicitly multithreaded due to some timer_settime()
+ implementations, therefore a signal sent to the group, can be sent
+ multiple times to this process. */
+ if (where == 0)
+ signal (sig, SIG_IGN);
return kill (where, sig);
}
@@ -160,11 +167,6 @@ cleanup (int sig)
}
if (monitored_pid)
{
- if (sigs_to_ignore[sig])
- {
- sigs_to_ignore[sig] = 0;
- return;
- }
if (kill_after)
{
/* Start a new timeout after which we'll send SIGKILL. */