Give up on the "try and compensate for broken programs" cruft and revert
back to the original single nanosleep() implementation. This is POSIX and Unix98 (aka single-unix spec v2) compliant behavior. If a program sets alarm(2) or an interval timer (setitimer(2)) without a SIGALRM handler being active, sleep(3) will no longer absorb it, and the program will get what it asked for..... :-] The original reason for this in the first place (apache) doesn't seem to need it anymore, according to Andrey. Reviewed by: ache, bde
This commit is contained in:
parent
d4efecb283
commit
9f375c3252
@ -38,24 +38,11 @@ static char sccsid[] = "@(#)sleep.c 8.1 (Berkeley) 6/4/93";
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef _THREAD_SAFE
|
|
||||||
#include <pthread.h>
|
|
||||||
#include "pthread_private.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _THREAD_SAFE
|
|
||||||
static void
|
|
||||||
sleephandler()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif /* _THREAD_SAFE */
|
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
sleep(seconds)
|
sleep(seconds)
|
||||||
unsigned int seconds;
|
unsigned int seconds;
|
||||||
{
|
{
|
||||||
#ifdef _THREAD_SAFE
|
|
||||||
struct timespec time_to_sleep;
|
struct timespec time_to_sleep;
|
||||||
struct timespec time_remaining;
|
struct timespec time_remaining;
|
||||||
|
|
||||||
@ -68,61 +55,4 @@ sleep(seconds)
|
|||||||
seconds++; /* round up */
|
seconds++; /* round up */
|
||||||
}
|
}
|
||||||
return (seconds);
|
return (seconds);
|
||||||
#else
|
|
||||||
struct timespec time_to_sleep;
|
|
||||||
struct timespec time_remaining;
|
|
||||||
struct sigaction act, oact;
|
|
||||||
sigset_t mask, omask;
|
|
||||||
int alarm_blocked;
|
|
||||||
|
|
||||||
if (seconds != 0) {
|
|
||||||
time_to_sleep.tv_sec = seconds;
|
|
||||||
time_to_sleep.tv_nsec = 0;
|
|
||||||
|
|
||||||
/* Block SIGALRM while fiddling with it */
|
|
||||||
sigemptyset(&mask);
|
|
||||||
sigaddset(&mask, SIGALRM);
|
|
||||||
if (sigprocmask(SIG_BLOCK, &mask, &omask))
|
|
||||||
return (seconds);
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
if (sigaction(SIGALRM, &act, &oact)) {
|
|
||||||
(void)sigprocmask(SIG_SETMASK, &omask,
|
|
||||||
(sigset_t *)0);
|
|
||||||
return (seconds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
(void)signanosleep(&time_to_sleep, &time_remaining, &omask);
|
|
||||||
|
|
||||||
if (!alarm_blocked) {
|
|
||||||
/* Unwind */
|
|
||||||
(void)sigaction(SIGALRM, &oact, (struct sigaction *)0);
|
|
||||||
(void)sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return how long is left */
|
|
||||||
seconds = time_remaining.tv_sec;
|
|
||||||
if (time_remaining.tv_nsec > 0)
|
|
||||||
seconds++; /* round up */
|
|
||||||
}
|
|
||||||
return (seconds);
|
|
||||||
#endif /* _THREAD_SAFE */
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user