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.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/libc/unistd/sleep.c b/libc/unistd/sleep.c
index 55e646380..481e635a2 100644
--- a/libc/unistd/sleep.c
+++ b/libc/unistd/sleep.c
@@ -50,6 +50,7 @@ unsigned int sleep (unsigned int seconds)
{
struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 };
sigset_t set;
+ struct sigaction oact;
unsigned int result;
/* This is not necessary but some buggy programs depend on this. */
@@ -62,33 +63,28 @@ unsigned int sleep (unsigned int seconds)
/* 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. */
+ in libc. */
+
__sigemptyset (&set);
__sigaddset (&set, SIGCHLD);
- sigprocmask (SIG_BLOCK, &set, &set); /* never fails */
- /* If SIGCHLD was already blocked, no need to check SIG_IGN. Else... */
+ /* Is SIGCHLD set to SIG_IGN? */
+ sigaction (SIGCHLD, NULL, &oact); /* never fails */
+ if (oact.sa_handler == SIG_IGN) {
+ /* Yes. Block SIGCHLD, save old mask. */
+ sigprocmask (SIG_BLOCK, &set, &set); /* never fails */
+ }
+
+ /* Run nanosleep, with SIGCHLD blocked if SIGCHLD is SIG_IGNed. */
+ result = nanosleep (&ts, &ts);
+
if (!__sigismember (&set, SIGCHLD)) {
- struct sigaction oact;
-
- /* Is SIGCHLD set to SIG_IGN? */
- sigaction (SIGCHLD, NULL, &oact); /* never fails */
- if (oact.sa_handler == SIG_IGN) {
- /* Yes, run nanosleep with SIGCHLD blocked. */
- result = nanosleep (&ts, &ts);
-
- /* 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. */
- sigprocmask (SIG_SETMASK, &set, NULL);
- } else {
- /* No workaround needed, unblock SIGCHLD by restoring signal mask. */
- sigprocmask (SIG_SETMASK, &set, NULL);
- result = nanosleep (&ts, &ts);
- }
+ /* We did block SIGCHLD, and old mask had no SIGCHLD bit.
+ IOW: we need to unblock SIGCHLD now. Do it. */
+ /* this sigprocmask call never fails, thus never updates errno,
+ and therefore we don't need to save/restore it. */
+ sigprocmask (SIG_SETMASK, &set, NULL); /* never fails */
}
- else
- result = nanosleep (&ts, &ts);
if (result != 0)
/* Round remaining time. */