On Wed, Nov 05, 2003 at 03:58:54PM -0000, [EMAIL PROTECTED] (via RT) wrote:
> It seems that in some environments (but not all), ignoring SIGCHLD
> corrputs the return value of system().

Thanks for the report, but I think this is the expected behavior.

To make a long story short: Linux is one of the platforms where ignoring
SIGCHLD turns on auto-reaping of child processes.  Perl's system() calls
(some flavor of) waitpid() to get the exit status of the child process.
And as described in perlipc, waitpid() can fail when children are being
automatically reaped.

That's enough to explain the failures you saw.  But according to the Linux
wait(2) manpage:

    if a wait() or waitpid() call is made while SIGCHLD is being ignored,
    the call behaves just as though SIGCHLD were not being igored, that
    is, the call blocks until the next child terminates and then returns
    the PID and status of that child.

So you've actually got a race on Linux.  If perl calls waitpid() before
the child exits, waitpid() -- and therefore system() -- will succeed.  If
the child exits first, it will be reaped automatically, causing waitpid()
to fail with ECHILD and system() to return -1.

    % cat -n sig.pl
     1  $SIG{CHLD} = "IGNORE";
     2  
     3  my ($cmd, $count) = @ARGV;
     4  my $fails = 0;
     5  
     6  for (1..$count) { $fails++ if system($cmd) == -1 }
     7  
     8  print "failed $fails/$count times\n";

    % sig.pl true 1000
    failed 6/1000 times

-- 
Steve

Reply via email to