summaryrefslogtreecommitdiff
path: root/libc/unistd/sleep.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/unistd/sleep.c')
-rw-r--r--libc/unistd/sleep.c47
1 files changed, 21 insertions, 26 deletions
diff --git a/libc/unistd/sleep.c b/libc/unistd/sleep.c
index b0031f022..d844d5b11 100644
--- a/libc/unistd/sleep.c
+++ b/libc/unistd/sleep.c
@@ -49,50 +49,45 @@ unsigned int sleep (unsigned int sec)
unsigned int sleep (unsigned int seconds)
{
struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 };
- sigset_t set, oset;
+ sigset_t set;
unsigned int result;
/* This is not necessary but some buggy programs depend on this. */
- if (seconds == 0)
- {
+ if (seconds == 0) {
# ifdef CANCELLATION_P
- CANCELLATION_P (THREAD_SELF);
+ CANCELLATION_P (THREAD_SELF);
# endif
- return 0;
- }
+ return 0;
+ }
/* Linux will wake up the system call, nanosleep, when SIGCHLD
arrives even if SIGCHLD is ignored. We have to deal with it
in libc. We block SIGCHLD first. */
__sigemptyset (&set);
__sigaddset (&set, SIGCHLD);
- sigprocmask (SIG_BLOCK, &set, &oset); /* can't fail */
+ sigprocmask (SIG_BLOCK, &set, &set); /* never fails */
- /* If SIGCHLD is already blocked, we don't have to do anything. */
- if (!__sigismember (&oset, SIGCHLD))
- {
- int saved_errno;
+ /* If SIGCHLD was already blocked, no need to check SIG_IGN. Else... */
+ if (!__sigismember (&set, SIGCHLD)) {
struct sigaction oact;
- __sigemptyset (&set);
- __sigaddset (&set, SIGCHLD);
-
+ /* Is SIGCHLD set to SIG_IGN? */
sigaction (SIGCHLD, NULL, &oact); /* never fails */
+ if (oact.sa_handler == SIG_IGN) {
+ //int saved_errno;
- if (oact.sa_handler == SIG_IGN)
- {
- /* We should leave SIGCHLD blocked. */
+ /* Yes, run nanosleep with SIGCHLD blocked. */
result = nanosleep (&ts, &ts);
- saved_errno = errno;
- /* Restore the original signal mask. */
- sigprocmask (SIG_SETMASK, &oset, NULL);
- __set_errno (saved_errno);
- }
- else
- {
- /* We should unblock SIGCHLD. Restore the original signal mask. */
- sigprocmask (SIG_SETMASK, &oset, NULL);
+ /* Unblock SIGCHLD by restoring signal mask. */
+ /* this sigprocmask call never fails, thus never updates errno,
+ and therefore we don't need to save/restore it. */
+ //saved_errno = errno;
+ sigprocmask (SIG_SETMASK, &set, NULL);
+ //__set_errno (saved_errno);
+ } else {
+ /* No workaround needed, unblock SIGCHLD by restoring signal mask. */
+ sigprocmask (SIG_SETMASK, &set, NULL);
result = nanosleep (&ts, &ts);
}
}