What is the difference between these settings?
$SIG{CHLD} = 'IGNORE'
$SIG{CHLD} = 'DEFAULT'
$SIG{CHLD} = ''
$SIG{CHLD} = undef
According to "Advanced Programming in the UNIX Environment, 2nd edition", figure 10.1 the default value of SIGCHLD is "ignore."
If "ignore" meant "SIG_IGN", then no child would ever be a zombie, and that's not the case.
It doesn't get much more clear from there:
If the process specifically sets its disposition to SIG_IGN, children of the calling process will not generate zombie processes. Note that this is different from its default action (SIG_DFL), which from Figure 10.1 is to be ignored. Instead, on termination, the status of these child processes is discarded.
I'm having a hard time groking what the impact of the various values (or undefined non-value) are. So far, the solution has been to rotate through those choices until I get the desired behavior, and I'd rather understand exactly how each value defines the behavior of the signal.
The behavior: a child process is calling "system" or using backticks which create another child, and the signal would normally be caught by the wrong (parent) handler. Setting a local handler can work, but I don't understand which value is most appropriate if I want the signal from the grand-child to do nothing.
Could someone please illuminate me?
UPDATE: Based on ikegami's feedback, I did some specific testing. The behavior is, at least partially, platform specific.
Consider the following fragment:
$SIG{CHLD} = sub {
while( ( my $child = waitpid( -1, &WNOHANG ) ) > 0 ) {
print "SIGNAL CHLD $child\n";
}
};
my $pid = fork();
if( ! $pid ) {
system( 'echo Grandchild PID = $$' );
sleep 2;
exit;
}
print "Child PID = $pid\n";
sleep 5;
Perl 5.8.6 on Solaris 10 will display "SIGNAL CHLD" messages for the PID of the system() call. Doing anything, even as trivial as
local $SIG{CHLD};
in the child will suppress those messages.
On every other flavor I tried, the reaper never sees the child.
See %SIG
.
$SIG{CHLD} = 'IGNORE';
causes your process to ignore SIGCHLD signals.
$SIG{CHLD} = 'DEFAULT';
causes your process to treat SIGCHLD signals as it would had you not messed with $SIG{CHLD}
or equivalent. According to kill(1), a process on my system ignores SIGCHLD by default
$SIG{CHLD} = '';
and $SIG{CHLD} = undef;
are not valid values.
As for reaping, children of a parent whose SIGCHLD handler is explicitely set to IGNORE
will be reaped automatically by the system as soon as it exits.
$ perl -e'
my $pid = fork;
if (!$pid) { sleep(1); exit; }
sleep(2);
system "ps -o pid,stat,command $pid";
'
PID STAT COMMAND
14667 ZN+ [perl] <defunct>
$ perl -e'
$SIG{CHLD}="IGNORE";
my $pid = fork;
if (!$pid) { sleep(1); exit; }
sleep(2);
system "ps -o pid,stat,command $pid";
'
PID STAT COMMAND
$