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 :-)
This commit is contained in:
Andrey A. Chernov 1997-08-12 19:14:54 +00:00
parent 0b6e0f74f9
commit 8d7bf613b2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=28125
2 changed files with 58 additions and 38 deletions

View File

@ -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;

View File

@ -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 */
}