This is the mail archive of the
libc-hacker@sourceware.cygnus.com
mailing list for the glibc project.
Re: sleep ignore sigchld
- To: AEH@akc.org (Adrian Hands)
- Subject: Re: sleep ignore sigchld
- Date: Mon, 16 Nov 1998 09:29:07 -0800 (PST)
- Cc: linux-kernel@vger.rutgers.edu (linux kernel),torvalds@transmeta.com (Linus Torvalds)
>
> I appologize for taking so long to get back to you.
> Here's a simpler program that demonstrates the unexpected
> behaviour I get from sleep() and SIGCHLD.
> I've included a sample run and "strace" as you requested.
> It's not necessarily a bug ¯-
> ¯ It's just that on other Unixes sleep() will not be
> interrupted by receiving SIGCHLD when SIGCHLD has been set to
> SIG_IGN.
> On RedHat 5.1 (linux 2.0.34) it seems that sleep IS interrupted
> even when the signal is ignored.
>
> [adrian@india adrian]$ cat trash2.c
> #include <stdio.h>
> #include <signal.h>
>
> int main(int argc, char * argv[]) {
> int i_slept;
> signal(SIGCHLD, SIG_IGN);
> if(fork() != 0) {
> i_slept = sleep(10);
> printf("Parent woke up after %d (should be 10)\n",
> 10 - i_slept
> );
> } else {
> sleep(3);
> _exit(0);
> }
> }
> [adrian@india adrian]$
> [adrian@india adrian]$
> [adrian@india adrian]$ cc trash2.c && ./a.out
> Parent woke up after 3 (should be 10)
> [adrian@india adrian]$
> [adrian@india adrian]$
> [adrian@india adrian]$ strace ./a.out
> execve("./a.out", ["./a.out"], [/* 22 vars */]) = 0
> brk(0) = 0x80496d4
> open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory)
> open("/etc/ld.so.cache", O_RDONLY) = 3
> fstat(3, {st_mode=0, st_size=0, ...}) = 0
> mmap(0, 14284, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4000b000
> close(3) = 0
> open("/lib/libc.so.6", O_RDONLY) = 3
> mmap(0, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4000f000
> munmap(0x4000f000, 4096) = 0
> mmap(0, 670420, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x4000f000
> mprotect(0x400a0000, 76500, PROT_NONE) = 0
> mmap(0x400a0000, 28672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x90000) = 0x400a0000
> mmap(0x400a7000, 47828, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x400a7000
> close(3) = 0
> personality(PER_LINUX) = 0
> getpid() = 1375
> sigaction(SIGCHLD, {SIG_IGN}, {SIG_DFL}) = 0
> fork() = 1376
> nanosleep(0xbffffd58, 0xbffffd58, 0x400a5ddc, 0x1, 0x80484bc) = -1 EINTR (Interrupted system call)
> --- SIGCHLD (Child exited) ---
That is a kernel bug. SIGCHLD is a special one. Usually it cannot
be ignored. The older libc. Solaris and Hp-UX use alarm/pause to
implement sleep. It goes back to sleep when SIGCHLD arrives if
SIGCHLD is ignored. The problem is glibc uses nanosleep to implement
sleep. The bug is in nanosleep in kernel. I don't think nanosleep
should wake up when SIGCHLD arrives if SIGCHLD is ignored. We have
to treat SIGCHLD specially for nanosleep.
H.J.