DEV Community

Aldora
Aldora

Posted on β€’ Edited on

3 1

PHP Child Process and Signal-Part 1

Take-away

  • PHP: no native support for multithreads
  • Alternative:pcntl_fork() create child processes
  • Reap child processes: pcntl_wait() and pcntl_signal()
    • pcntl_wait() can only handles the status of child process, totally no reaction for status of parent process.
    • pcntl_wait() has no effect when it is called in child process
    • pcntl_signal() only works for the process it is in, which means if I kill parent process, the signal handler in child won't work. While pcntl_wait() works for signals. If I kill the child, the pcntl_wait() in parent would detect it.

Create Child Processes: pcntl_fork()

if ($pid = pcntl_fork()) {
    $parent = getmypid();
    echo "parent: $parent\n";
} else {
    $childPid = getmypid();
    echo "child pid: $childPid\n";
}
Enter fullscreen mode Exit fullscreen mode

(Above example is from Advanced PHP Programming by George Schlossnagle)

The point pcntl_fork() called, child process would be created. In parent process, pcntl_fork() returns the pid of child process, while in the child, it returns 0.

Reap child processes: pcntl_wait() and pcntl_signal()

pcntl_wait() would wait on or returns the status of a forked child. It instructs the calling process to suspend execution until any of its children terminates. Note two things:

  • it can only handles the status of child process, totally no reaction for status of parent process.
  • it has no effect when it is called in child process More detail here.

Detailed example: Cleaning Up After Children part

pcntl_signal would install a signal handler. Signals are the instruction to processes. For example, when we execute command kill to terminate a process, system would send interrupt signal SIGINT. With signal handler, we could define our function to deal with process.
The following example shows how we use them to reap child process.

pcntl_async_signals(true);

pcntl_signal(SIGTERM, function ($signal, $status) {
    echo "inside pcntl_signal\n";
    $pid = pcntl_wait($processStatus, WUNTRACED);
//    $pid = pcntl_wait($processStatus, WNOHANG);

    if (pcntl_wifexited($processStatus)) {
        $code = pcntl_wexitstatus($processStatus);
        print "pid $pid returned exit code: $code\n ";
    } else {
        print "$pid was unnaturally terminated\n ";
    }
//    print_r($processStatus);
//    echo "\n";
//    echo "signal: $signal\n";
//    print_r($status);
});
if ($pid = pcntl_fork()) {
    $parent = getmypid();
    echo "parent: $parent\n";

    sleep(60);
} else {
    $childPid = getmypid();
    echo "child pid: $childPid\n";

    sleep(60);
}
Enter fullscreen mode Exit fullscreen mode

Execute the above script, and according to the output of process pid, first use kill command to kill parent process, then kill child process. The total output would be like this:

parent: <parent pid>
child pid: <child pid>
inside pcntl_signal  //shows when parent gets killed
inside pcntl_signal //shows when child gets killed
pid -1 returned exit code: 0
pid <child pid> returned exit code: 0
Enter fullscreen mode Exit fullscreen mode

So what happened? First we execute the script, it create a parent process and a child. Then we kill parent, which send a SIGINT signal, it invokes the signal handler in parent process. So we get the first 'inside pcntl_signal', and because pcntl_wait only works for forked processes, so it can't handle the signal of parent. The parameter in pcntl_wait is 'WUNTRACED', which means it would wait until it gets a valid signal from the child.
Then we kill the child process, once again, it invokes signal handler. But why there are two lines of 'pid * returned exit code *'? Because the pcntl_wait in parent is working. 'pid -1 returned exit code: 0' is returned from child process, cause pcntl_wait() has no effect when called in child. The pcntl_wait() in parent successfully detects the exit of child process.

So what would happen if we kill child first, then kill the parent?

AWS Industries LIVE! Stream

Watch AWS Industries LIVE!

Watch Industries LIVE! to find out how the AWS cloud helps solve real-world business challenges.

Learn More

Top comments (0)

Image of Stellar post

Check out Episode 1: How a Hackathon Project Became a Web3 Startup πŸš€

Ever wondered what it takes to build a web3 startup from scratch? In the Stellar Dev Diaries series, we follow the journey of a team of developers building on the Stellar Network as they go from hackathon win to getting funded and launching on mainnet.

Read more

πŸ‘‹ Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay