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