There is following paragraph in SUSv2:
If a process sets the action for the SIGCHLD signal to SIG_IGN,
the behaviour is unspecified, except as specified below. If the
action for the SIGCHLD signal is set to SIG_IGN, child processes
of the calling processes will not be transformed into zombie
processes when they terminate. If the calling process subsequently
waits for its children, and the process has no unwaited for children
that were transformed into zombie processes, it will block until all
of its children terminate, and wait(), wait3(), waitid() and waitpid()
will fail and set errno to [ECHILD]. ...
However, if I use "signal(SIGCHLD, SIG_IGN)", zombies are still
created in FreeBSD, which is against SUSv2.
What do you think about following patch for -stable (it is
usable with -current too)? Furthermore, it seems that the test
"if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] = SIG_IGN)" is unnecessary.
After patch there are: one more question, comparison results among
different systems (unbelievable how much they are different :-) and
my sigtest.c program:
-- Patch
--- sys/kern/kern_sig.c.orig Wed Jun 6 11:52:37 2001
+++ sys/kern/kern_sig.c Thu Jun 7 11:57:45 2001
@@ -438,6 +438,8 @@
* Reset no zombies if child dies flag as Solaris does.
*/
p->p_procsig->ps_flag &= ~PS_NOCLDWAIT;
+ if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] = SIG_IGN)
+ ps->ps_sigact[_SIG_IDX(SIGCHLD)] = SIG_DFL;
}
/*
--- sys/kern/kern_exit.c.orig Wed Jun 6 13:13:43 2001
+++ sys/kern/kern_exit.c Thu Jun 7 11:24:03 2001
@@ -316,7 +316,8 @@
* flag set, notify process 1 instead (and hope it will handle
* this situation).
*/
- if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT) {
+ if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT
+ || p->p_sigacts->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN) {
struct proc *pp = p->p_pptr;
proc_reparent(p, initproc);
/*
-- Question
In sys/kern/kern_sig.c in do_sigaction(), there is:
if (act->sa_flags & SA_SIGINFO) {
ps->ps_sigact[_SIG_IDX(sig)] = act->sa_handler;
SIGADDSET(ps->ps_siginfo, sig);
} else {
ps->ps_sigact[_SIG_IDX(sig)] =
(__sighandler_t *)act->sa_sigaction;
SIGDELSET(ps->ps_siginfo, sig);
}
Why? I know that sa_handler and sa_sigaction are the same pointer in
an union, but I think that "act->sa_handler" should be exchanged with
"(__sighandler_t *)act->sa_sigaction" for clarification purposes.
-- Comparison results
ABCD(Z = zombie created): SIGCHLD properties before exec() -> after exec()
A) SIG_IGN before exec (instead of SIG_DFL)
B) SA_NOCLDWAIT before exec (instead of 0)
C) SIG_IGN after exec (instead of SIG_DFL)
D) SA_NOCLDWAIT after exec (instead of 0)
Solaris 2.7, FreeBSD 4.3 with proposed patch:
0000(Z), 0001( ), 0010( ), 0011( ): SIG_DFL() -> SIG_DFL()
0100(Z), 0101( ), 0110( ), 0111( ): SIG_DFL(SA_NOCLDWAIT) -> SIG_DFL()
1000(Z), 1001( ), 1010( ), 1011( ): SIG_IGN() -> SIG_DFL()
1100(Z), 1101( ), 1110( ), 1111( ): SIG_IGN(SA_NOCLDWAIT) -> SIG_DFL()
Irix 6.5, Unixware 7.0.1:
0000(Z), 0001( ), 0010( ), 0011( ): SIG_DFL() -> SIG_DFL()
0100(Z), 0101( ), 0110( ), 0111( ): SIG_DFL(SA_NOCLDWAIT) -> SIG_DFL()
1000(Z), 1001( ), 1010( ), 1011( ): SIG_IGN(SA_NOCLDWAIT) -> SIG_IGN()
1100(Z), 1101( ), 1110( ), 1111( ): SIG_IGN(SA_NOCLDWAIT) -> SIG_IGN()
FreeBSD 4.3 without proposed patch, FreeBSD-current (Apr 27):
0000(Z), 0001( ), 0010(Z), 0011( ): SIG_DFL() -> SIG_DFL()
0100(Z), 0101( ), 0110(Z), 0111( ): SIG_DFL(SA_NOCLDWAIT) -> SIG_DFL()
1000(Z), 1001( ), 1010(Z), 1011( ): SIG_IGN() -> SIG_IGN()
1100(Z), 1101( ), 1110(Z), 1111( ): SIG_IGN(SA_NOCLDWAIT) -> SIG_IGN()
Linux 2.2.17:
0000(Z), 0001(Z), 0010( ), 0011( ): SIG_DFL() -> SIG_DFL()
0100(Z), 0101(Z), 0110( ), 0111( ): SIG_DFL(SA_NOCLDWAIT) -> SIG_DFL()
1000( ), 1001(Z), 1010( ), 1011( ): SIG_IGN() -> SIG_IGN()
1100( ), 1101(Z), 1110( ), 1111( ): SIG_IGN(SA_NOCLDWAIT) -> SIG_IGN()
-- testsig.c
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
int childs = 0;
struct sigaction sa, so;
int status;
int value;
if (argc > 1) {
value = atoi(argv[1]);
} else {
printf("Usage: sigtest <value 0..15>\n");
exit(1);
}
if (argc > 2 && strcmp(argv[2], "-x") == 0) {
/* After exec() */
sigaction(SIGCHLD, NULL, &so);
printf("After exec(): %s(%s)\n",
(so.sa_handler == SIG_IGN) ? "SIG_IGN"
: ((so.sa_handler == SIG_DFL) ? "SIG_DFL" : "?"),
(so.sa_flags & SA_NOCLDWAIT) ? "SA_NOCLDWAIT" : "");
sigemptyset(&sa.sa_mask);
if (value & 3) {
sa.sa_flags = (value & 1) ? SA_NOCLDWAIT : 0;
sa.sa_handler = (value & 2) ? SIG_IGN : SIG_DFL;
sigaction(SIGCHLD, &sa, NULL);
}
sigaction(SIGCHLD, NULL, &so);
printf("Before fork(): %s(%s)\n",
(so.sa_handler == SIG_IGN) ? "SIG_IGN"
: ((so.sa_handler == SIG_DFL) ? "SIG_DFL" : "?"),
(so.sa_flags & SA_NOCLDWAIT) ? "SA_NOCLDWAIT" : "");
while (++childs <= 10) {
switch (fork())
{
case 0:
printf("Child %d exiting...\n", childs);
exit(0);
case -1:
printf("fork(): %s\n", strerror(errno));
exit(-1);
default:
break;
}
}
printf("Sleeping...\n");
sleep(3);
} else {
/* Main process before exec() */
switch (fork())
{
case 0:
sigaction(SIGCHLD, NULL, &so);
printf("Default: %s(%s)\n",
(so.sa_handler == SIG_IGN) ? "SIG_IGN"
: ((so.sa_handler == SIG_DFL) ? "SIG_DFL" : "?"),
(so.sa_flags & SA_NOCLDWAIT) ? "SA_NOCLDWAIT" : "");
sigemptyset(&sa.sa_mask);
if (value & 12) {
sa.sa_flags = (value & 4) ? SA_NOCLDWAIT : 0;
sa.sa_handler = (value & 8) ? SIG_IGN : SIG_DFL;
sigaction(SIGCHLD, &sa, NULL);
}
sigaction(SIGCHLD, NULL, &so);
printf("Before exec(): %s(%s)\n",
(so.sa_handler == SIG_IGN) ? "SIG_IGN"
: ((so.sa_handler == SIG_DFL) ? "SIG_DFL" : "?"),
(so.sa_flags & SA_NOCLDWAIT) ? "SA_NOCLDWAIT" : "");
execl(argv[0], argv[0], argv[1], "-x", NULL);
printf("exec(%s %s): %s\n", argv[0], "-x", strerror(errno));
return 0;
case -1:
printf("fork(): %s\n", strerror(errno));
exit(-1);
default:
(void)wait(&status);
break;
}
}
return 0;
}
--
Rudolf Cejka ([EMAIL PROTECTED]; http://www.fee.vutbr.cz/~cejkar)
Brno University of Technology, Faculty of El. Engineering and Comp. Science
Bozetechova 2, 612 66 Brno, Czech Republic
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message