summaryrefslogtreecommitdiffstats
path: root/bin/sh/trap.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2012-07-29 18:04:38 +0000
committerjilles <jilles@FreeBSD.org>2012-07-29 18:04:38 +0000
commit0df7adbcbe3c3afbf692f3f73ca539615d63b08b (patch)
treea060f3bd159c1ec22e9713a49fd8f32e73254f50 /bin/sh/trap.c
parentdebac64ecce4854e463c0578506d8fec17363684 (diff)
downloadFreeBSD-src-0df7adbcbe3c3afbf692f3f73ca539615d63b08b.zip
FreeBSD-src-0df7adbcbe3c3afbf692f3f73ca539615d63b08b.tar.gz
sh: Fix EINTR race condition in "wait" and "set -T" using sigsuspend().
When waiting for child processes using "wait" or if "set -T" is in effect, a signal interrupts the wait. Make sure there is no window where the signal handler may be invoked (setting a flag) just before going to sleep. There is a similar race condition in the shell language, but scripts can avoid it by exiting from the trap handler or enforcing synchronization using a fifo. If SIGCHLD is not trapped, a signal handler must be installed for it. Only install this handler for the duration of the wait to avoid triggering unexpected [EINTR] errors elsewhere. Note that for some reason only SIGINT and SIGQUIT interrupt a "wait" command. This remains the case.
Diffstat (limited to 'bin/sh/trap.c')
-rw-r--r--bin/sh/trap.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index 94cf129..521c511 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -368,6 +368,14 @@ ignoresig(int signo)
}
+int
+issigchldtrapped(void)
+{
+
+ return (trap[SIGCHLD] != NULL && *trap[SIGCHLD] != '\0');
+}
+
+
/*
* Signal handler.
*/
OpenPOWER on IntegriCloud