Duplication of resources when forking

When you fork a child from your PHP script, that child inherits all variables and resources that were opened by its parent. In the case of files, both parent and child inherit the same file descriptors which means that you can write to the same file from several processes if you want to. In practice this is undesirable as you will get intermingled lines of text from the different process, however there's no harm seeing how it's done just in case!

This next example opens the file "forktest" and has each child write two lines into it:

<?php
    $fp = fopen("forktest", "a");

    for ($i = 1; $i <= 5; ++$i) {
        $pid = pcntl_fork();

        if (!$pid) {
            fwrite($fp, "In child $i\n");
            sleep(1);
            fwrite($fp, "Still in child $i\n");
            exit($i);
        }
    }
?>

Once that script has executed, the forktest file should be filled with this text:

In child 1
In child 2
In child 3
In child 4
In child 5
Still in child 1
Still in child 2
Still in child 3
Still in child 4
Still in child 5

Similarly you can have all your children connect to a MySQL database just by connecting once. First, create a table in your phpdb database using the following command:

CREATE TABLE forktest (StringVal CHAR(255));

Now, save this next script as forkdb.php and run it:

<?php
    $db = mysqli_connect("p:localhost", "phpuser", "alm65z", "phpdb");
    mysqli_query($db, "INSERT INTO forktest VALUES ('Parent about to fork children');");

    for ($i = 1; $i <= 5; ++$i) {
        $pid = pcntl_fork();

        if (!$pid) {
            mysqli_query($db, "INSERT INTO forktest VALUES ('In child $i');");
            exit($i);
        }
    }

    mysqli_query($db, "INSERT INTO forktest VALUES ('Parent exiting...');");
?>

After the script completes, you should have seven rows in the table charting the progress of your script, all by connecting just once. Appearances are deceiving, however - if you try running the above script yourself you will find that PHP actually makes several connections to MySQL. This is where you start getting into the realms of the unknown, by which I mean that sharing resources across processes is a hairy business best left alone if possible.

The solution here is to have children open their own resources up. This makes your code clearer, avoids problems with processes treading on each other's toes, and also means you will be less likely to encounter cross-platform problems with your code.

 

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: The third parameter to pcntl_waitpid() >>

Previous chapter: Getting into multiprocessing

Jump to:

 

Home: Table of Contents

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