mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 01:38:57 +00:00
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
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=30442
@ -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 */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user