ajaxperlforkexitqx

Fork in perl but get exit status from a system call in the child process


What I do:

  1. Make an ajax call to a cgi script.
  2. Cgi script forks but the parent returns right away with a response msg.
  3. The child does a system call but needs the exit code and any error messages.

Pseudo-code:

$SIG{CHLD} = ‘IGNORE’; # or waitpid($pid,0) in the parent process
$pid = fork();
if($pid == 0)
{
    close STDOUT; # So that the parent sends the response to the client right away.

    @errorMsgs = qx(tar up big directories over 50G…); # This can go on for a few minutes.

    if($? ==0) { Send a ‘success’ email } # Is always false ($? == -1)

    else { Send a ‘failure’ email }
}
elsif($pid){ sendResponse; waitpid($pid,0) if $SIG{CHLD} != 'IGNORE'; exit;}

My problem:

Trouble getting a correct return code ($?) and any error messages from qx() as it is set to -1 due to ($SIG{CHLD} = 'IGNORE'). If I remove $SIG{CHLD} statement, the client web page does not receive a response msg from the parent until after the child is reaped.


Solution

  • You're getting a -1 because you're setting $SIG{CHLD} to IGNORE. By doing that, you're killing qx's ability to capture the exit code of tar... it will die without notifying the parent (your child process).

    It's simple enough to test out:

    perl -e '$SIG{CHLD} = "IGNORE"; system("ps"); print "Finished with $?\n";
    

    This gives -1.

    perl -e 'system("ps"); print "Finished with $?\n";
    

    This gives 0.

    If you really need the $SIG{CHLD} = 'IGNORE', then just $SIG{CHLD} = 'DEFAULT' before your qx call.

    Also, make sure you're using the full path to tar (e.g. /bin/tar) just in case you don't have /bin in your path, and it's failing to execute. However, I'm assuming that's OK since you didn't say anything about your tar file not being created.