summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>1997-08-12 19:14:54 +0000
committerache <ache@FreeBSD.org>1997-08-12 19:14:54 +0000
commitf9a8aa567ee01aa0b4cc41b2b6d6c509562ef435 (patch)
tree8d68df4fcba5061b8d20725693409b71a0efd7e8 /lib
parent782a1cf6417eea958316a96b200971eb43b1f3ce (diff)
downloadFreeBSD-src-f9a8aa567ee01aa0b4cc41b2b6d6c509562ef435.zip
FreeBSD-src-f9a8aa567ee01aa0b4cc41b2b6d6c509562ef435.tar.gz
Back out my installation of SIGALRM handler even if it is blocked
and return to previous Peter's variant. POSIX says that this place is implementation defined and old variant allows application block SIGALRM and sleep and not be killed by external SIGALRMs. BTW, GNU sleep f.e. sleeps forever in blocked SIGALRM :-)
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gen/sleep.c48
-rw-r--r--lib/libc/gen/usleep.c48
2 files changed, 58 insertions, 38 deletions
diff --git a/lib/libc/gen/sleep.c b/lib/libc/gen/sleep.c
index 485f778..b553bf7 100644
--- a/lib/libc/gen/sleep.c
+++ b/lib/libc/gen/sleep.c
@@ -87,6 +87,7 @@ sleep(seconds)
struct timespec time_remaining;
struct sigaction act, oact;
sigset_t mask, omask;
+ int alarm_blocked;
if (seconds != 0) {
/*
@@ -102,30 +103,39 @@ sleep(seconds)
time_to_sleep.tv_sec = seconds;
time_to_sleep.tv_nsec = 0;
- /*
- * Set up handler to interrupt signanosleep and ensure
- * SIGARLM is not blocked. Block SIGALRM while fiddling
- * with things.
- */
- memset(&act, 0, sizeof(act));
- act.sa_handler = sleephandler;
+ /* Block SIGALRM while fiddling with it */
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_BLOCK, &mask, &omask);
- sigaction(SIGALRM, &act, &oact);
- mask = omask;
- sigdelset(&mask, SIGALRM);
- /*
- * signanosleep() uses the given mask for the lifetime of
- * the syscall only - it resets on return. Note that the
- * old sleep explicitly unblocks SIGALRM during the sleep.
- */
- signanosleep(&time_to_sleep, &time_remaining, &mask);
+ /* Was SIGALRM blocked already? */
+ alarm_blocked = sigismember(&omask, SIGALRM);
- /* Unwind */
- sigaction(SIGALRM, &oact, (struct sigaction *)0);
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+ if (!alarm_blocked) {
+ /*
+ * Set up handler to interrupt signanosleep only if
+ * SIGALRM was unblocked. (Save some syscalls)
+ */
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sleephandler;
+ sigaction(SIGALRM, &act, &oact);
+ }
+
+ /*
+ * signanosleep() uses the given mask for the lifetime of
+ * the syscall only - it resets on return. Note that the
+ * old sleep() explicitly unblocks SIGALRM during the sleep,
+ * we don't do that now since we don't depend on SIGALRM
+ * to end the timeout. If the process blocks SIGALRM, it
+ * gets what it asks for.
+ */
+ signanosleep(&time_to_sleep, &time_remaining, &omask);
+
+ if (!alarm_blocked) {
+ /* Unwind */
+ sigaction(SIGALRM, &oact, (struct sigaction *)0);
+ sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+ }
/* return how long is left */
rest += time_remaining.tv_sec;
diff --git a/lib/libc/gen/usleep.c b/lib/libc/gen/usleep.c
index c8e26cb..85c75a4 100644
--- a/lib/libc/gen/usleep.c
+++ b/lib/libc/gen/usleep.c
@@ -76,42 +76,52 @@ usleep(useconds)
struct timespec time_remaining;
struct sigaction act, oact;
sigset_t mask, omask;
+ int alarm_blocked;
if (useconds != 0) {
time_to_sleep.tv_nsec = (useconds % 1000000) * 1000;
time_to_sleep.tv_sec = useconds / 1000000;
- /*
- * Set up handler to interrupt signanosleep and ensure
- * SIGARLM is not blocked. Block SIGALRM while fiddling
- * with things.
- */
- memset(&act, 0, sizeof(act));
- act.sa_handler = sleephandler;
+ /* Block SIGALRM while fiddling with it */
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_BLOCK, &mask, &omask);
- sigaction(SIGALRM, &act, &oact);
- mask = omask;
- sigdelset(&mask, SIGALRM);
+
alarm_termination = 0;
- /*
- * signanosleep() uses the given mask for the lifetime of
- * the syscall only - it resets on return. Note that the
- * old sleep explicitly unblocks SIGALRM during the sleep.
- */
+ /* Was SIGALRM blocked already? */
+ alarm_blocked = sigismember(&omask, SIGALRM);
+
+ if (!alarm_blocked) {
+ /*
+ * Set up handler to interrupt signanosleep only if
+ * SIGALRM was unblocked. (Save some syscalls)
+ */
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sleephandler;
+ sigaction(SIGALRM, &act, &oact);
+ }
+ /*
+ * signanosleep() uses the given mask for the lifetime of
+ * the syscall only - it resets on return. Note that the
+ * old sleep() explicitly unblocks SIGALRM during the sleep,
+ * we don't do that now since we don't depend on SIGALRM
+ * to end the timeout. If the process blocks SIGALRM, it
+ * gets what it asks for.
+ */
do {
- signanosleep(&time_to_sleep, &time_remaining, &mask);
+ signanosleep(&time_to_sleep, &time_remaining, &omask);
time_to_sleep = time_remaining;
} while (!alarm_termination &&
(time_to_sleep.tv_sec != 0 ||
time_to_sleep.tv_nsec != 0));
- /* Unwind */
- sigaction(SIGALRM, &oact, (struct sigaction *)0);
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+ if (!alarm_blocked) {
+ /* Unwind */
+ sigaction(SIGALRM, &oact, (struct sigaction *)0);
+ sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+ }
}
#endif /* _THREAD_SAFE */
}
OpenPOWER on IntegriCloud