16.1.6 Event-driven child terminationThis is NOT the latest copy of this book; click here for the latest version.
So far we've had to lock up our parent script while we wait for our children to finish executing, but we can combine the new-found knowledge of forking with the signals we saw earlier in this chapter to allow our parent process to execute freely until it gets notified that a child by the OS that a child finished.
To accomplish this feat we need to catch a new signal, SIGCHLD, which is sent when one or more child process has terminated. I say "one or more" on purpose: you may well get only one SIGCHLD call for several processes terminating, so you need to use the same pcntl_waitpid() while loop to ensure you catch them all in the same SIGCHLD handler.
So, what we're going to do is install a signal handler for SIGCHLD, use it to call pcntl_waitpid() to print out return information from the child scripts, then let the parent execute freely. Make sense? Good - here's how it looks in PHP:
<?php
declare(ticks = 1);
pcntl_signal(SIGCHLD, "signal_handler");
function signal_handler($signal) {
switch($signal) {
case SIGCHLD:
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed\n";
}
exit;
}
}
for ($i = 1; $i <= 5; ++$i) {
$pid = pcntl_fork();
if (!$pid) {
sleep(1);
print "In child $i\n";
exit($i);
}
}
while(1) {
// parent does processing here...
} ?>
The nice thing about that script is that it's simply a combination of our signal-handling script and our forking script: the only addition is the new SIGCHLD action. The advantages to forking this way should be clear: the parent process isn't left sitting around while the children are off doing cool stuff; instead, it can carry on processing a work load independently of its children, and gracefully handle child termination when ready. This actually works out as a smart way to write interactive applications: rather than have your users wait for an action to complete, why not fork it and let them continue using the parent, then notify them when the child has finished?
Author's Note: In the interest of balance, Tom Tromey (elite language hacker extraordinnaire) said that "wait and sigchld are one of the ugly warts on Unix". Go ahead and try it out, and see what you think.
|
Want to see this stuff in print? PHP in a Nutshell takes the core topics covered here, adds in thousands of edits from the editorial team and myself, and combines them to make an unbeatable reference for PHP programmers at all levels.
My latest book has hundreds more tips on how to use PHP, Apache, and MySQL, plus Perl, Python, shell scripts, performance tuning, and more!
|