atom feed17 messages in org.freebsd.freebsd-hackers[Patch?] signal(SIGCHLD, SIG_IGN) is ...
FromSent OnAttachments
Cejka RudolfJun 7, 2001 5:30 am 
Cejka RudolfJun 7, 2001 6:00 am 
Terry LambertJun 8, 2001 1:53 am 
Cejka RudolfJun 10, 2001 9:36 am 
Matt DillonJun 10, 2001 11:45 am 
Peter WemmJun 10, 2001 5:20 pm 
David MaloneJun 11, 2001 3:57 am 
Cejka RudolfJun 12, 2001 12:53 am 
Matt DillonJun 12, 2001 9:38 am 
David MaloneJun 13, 2001 2:09 am 
Terry LambertJun 13, 2001 11:04 pm 
Terry LambertJun 13, 2001 11:39 pm 
Matt DillonJun 13, 2001 11:56 pm 
Terry LambertJun 14, 2001 2:32 am 
Matt DillonJun 14, 2001 10:08 am 
Terry LambertJun 15, 2001 1:38 am 
Matt DillonJul 22, 2001 11:48 am 
Subject:[Patch?] signal(SIGCHLD, SIG_IGN) is against SUSv2
From:Cejka Rudolf (cej@dcse.fee.vutbr.cz)
Date:Jun 7, 2001 5:30:28 am
List:org.freebsd.freebsd-hackers

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; }

To Unsubscribe: send mail to majo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message