bin/48856: Setting SIGCHLD to SIG_IGN still leaves

Alex Semenyaka alexs at ratmir.ru
Mon Mar 31 16:40:07 PST 2003


The following reply was made to PR bin/48856; it has been noted by GNATS.

From: Alex Semenyaka <alexs at ratmir.ru>
To: freebsd-gnats-submit at FreeBSD.org, joelh at piqnet.org
Cc:  
Subject: bin/48856: Setting SIGCHLD to SIG_IGN still leaves
Date: Tue, 1 Apr 2003 04:37:02 +0400

 Well, the problem is that POSIX does NOT specify that child will not
 be in zombie-state if you did signal(SIGCHLD, SIG_IGN). According
 to POSIX you the behaviour will be undefined. That's why, I believe,
 people does not pay too much attention to the accurate realization
 of this mechanism. They usually imply that if you need such control 
 you will use sigaction().
 
 But I think that it will be better to fix this behaviour to make it
 compatible with Linux and SysV way. There are a lot of reasons for
 this, one of them - some programs even from the base system expect
 Linux-behaviour from libraries in this place (not in critical section,
 of course, but...). See:
 
 > cd /usr/bin
 > grep -r SIGCHLD /usr/src/* | grep SIG_IGN | grep signal | cut -d: -f1 | grep '\.c$' | sort -u | wc -l
 13
 
 
 There are two places to fix: 
  - first, it is signal() implementation in the libc,
  - second, it is uthread_init() in the libc_r.
 
 In the first case we need only to check if we deal with
 signal(SIGCHLD, SIG_IGN), and if so add SA_NOCLDWAIT to flags.
 That's simple and strightforward.
 
 Second case needs some explanations. The user-thread mechanism
 has some special interaction with the signal delivery mechanism.
 One part of this interaction is the additional layer between
 the standard user interface (set of sig... functions) and the
 kernel. There is special treatment of some signals on that layer.
 One of those signals is SIGCHLD: the only place uthreads tells
 what to do with it is initialization ( uthread_init() ). After
 then user's calls to sigaction() or signal() are NOT passed to
 the kernel so the flags such as SA_NOCLDWAIT could not be set.
 So the solution is simple here as well: we need just to set
 this flag in the procedure of standard uthreads SIGCHLD handler
 installation in uthread_init().
 
 Complete changes involve only 3 lines (2 in signal.c, 1 in
 uthread_init.c).
 
 I put this changes to the sources and compiled the program from
 the original PR both with -lc_r and without. In both cases there
 was no zombie.
 
 Here the result of cvs diff -u -U1:
 
 Index: libc/gen/signal.c
 ===================================================================
 RCS file: /usr/local/FreeBSD/src/lib/libc/gen/signal.c,v
 retrieving revision 1.3
 diff -u -U1 -r1.3 signal.c
 --- libc/gen/signal.c	1 Feb 2002 00:57:29 -0000	1.3
 +++ libc/gen/signal.c	31 Mar 2003 23:55:21 -0000
 @@ -61,2 +61,4 @@
  		sa.sa_flags |= SA_RESTART;
 +	if (s == SIGCHLD && a == SIG_IGN)
 +		sa.sa_flags |= SA_NOCLDWAIT;
  	if (_sigaction(s, &sa, &osa) < 0)
 Index: libc_r/uthread/uthread_init.c
 ===================================================================
 RCS file: /usr/local/FreeBSD/src/lib/libc_r/uthread/uthread_init.c,v
 retrieving revision 1.45
 diff -u -U1 -r1.45 uthread_init.c
 --- libc_r/uthread/uthread_init.c	11 Jan 2003 00:43:20 -0000	1.45
 +++ libc_r/uthread/uthread_init.c	31 Mar 2003 23:54:16 -0000
 @@ -438,3 +438,3 @@
  		act.sa_handler = (void (*) ()) _thread_sig_handler;
 -		act.sa_flags = SA_SIGINFO | SA_RESTART;
 +		act.sa_flags = SA_SIGINFO | SA_RESTART | SA_NOCLDWAIT;
 
 Hope it will be easely incorporated into the main repository.


More information about the freebsd-bugs mailing list