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:
Peter Wemm 1997-10-15 14:06:15 +00:00
parent d4efecb283
commit 9f375c3252
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=30442

View File

@ -38,24 +38,11 @@ static char sccsid[] = "@(#)sleep.c 8.1 (Berkeley) 6/4/93";
#include <sys/time.h>
#include <signal.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
sleep(seconds)
unsigned int seconds;
{
#ifdef _THREAD_SAFE
struct timespec time_to_sleep;
struct timespec time_remaining;
@ -68,61 +55,4 @@ sleep(seconds)
seconds++; /* round up */
}
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 */
}