Event-driven child termination

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 learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Other ways to evaluate pcntl_waitpid()'s return value >>

Previous chapter: The third parameter to pcntl_waitpid()

Jump to:

 

Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.