diff options
author | ache <ache@FreeBSD.org> | 1997-08-12 19:14:54 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 1997-08-12 19:14:54 +0000 |
commit | f9a8aa567ee01aa0b4cc41b2b6d6c509562ef435 (patch) | |
tree | 8d68df4fcba5061b8d20725693409b71a0efd7e8 | |
parent | 782a1cf6417eea958316a96b200971eb43b1f3ce (diff) | |
download | FreeBSD-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 :-)
-rw-r--r-- | lib/libc/gen/sleep.c | 48 | ||||
-rw-r--r-- | lib/libc/gen/usleep.c | 48 |
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 */ } |