* sysdeps/unix/sysv/linux/sleep.c (__sleep): Make Unix98 compliant
	by working removing SIG_IGN handler for SIGCHLD if necessary.
	Patch by H.J. Lu <hjl@lucon.org>.
This commit is contained in:
Ulrich Drepper 1998-11-17 20:39:52 +00:00
parent d8cceb4fcf
commit 45a9a50e68
2 changed files with 55 additions and 3 deletions

View File

@ -1,5 +1,9 @@
1998-11-17 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/unix/sysv/linux/sleep.c (__sleep): Make Unix98 compliant
by working removing SIG_IGN handler for SIGCHLD if necessary.
Patch by H.J. Lu <hjl@lucon.org>.
* stdio-common/printf_fphex.c (__printf_fphex): Correct printing
of denormalized numbers.

View File

@ -1,5 +1,5 @@
/* Implementation of the POSIX sleep function using nanosleep.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -18,18 +18,66 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
/* We are going to use the `nanosleep' syscall of the kernel. But the
kernel does not implement the sstupid SysV SIGCHLD vs. SIG_IGN
behaviour for this syscall. Therefore we have to emulate it here. */
unsigned int
__sleep (unsigned int seconds)
{
struct timespec ts = { tv_sec: (long int) seconds, tv_nsec: 0 };
sigset_t set, oset;
struct sigaction oact;
unsigned int result;
if (__nanosleep (&ts, &ts) == 0)
result = 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. */
if (__sigemptyset (&set) < 0
|| __sigaddset (&set, SIGCHLD) < 0
|| __sigprocmask (SIG_BLOCK, &set, &oset))
return -1;
/* If SIGCHLD is already blocked, we don't have to do anything. */
if (!__sigismember (&oset, SIGCHLD))
{
int saved_errno;
/* We get the signal handler for SIGCHLD. */
if (__sigaction (SIGCHLD, (struct sigaction *) NULL, &oact) < 0)
{
saved_errno = errno;
/* Restore the original signal mask. */
(void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
__set_errno (saved_errno);
return -1;
}
if (oact.sa_handler == SIG_IGN)
{
/* We should leave SIGCHLD blocked. */
result = __nanosleep (&ts, &ts);
saved_errno = errno;
/* Restore the original signal mask. */
(void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
__set_errno (saved_errno);
}
else
{
/* We should unblock SIGCHLD. Restore the original signal mask. */
(void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
result = __nanosleep (&ts, &ts);
}
}
else
result = __nanosleep (&ts, &ts);
if (result != 0)
/* Round remaining time. */
result = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L);