note 100557 added to function.pcntl-fork
| From: | sean dot kelly at mediatile dot com | Date: | Sat, 23 Oct 2010 00:36:20 +0000 |
| Subject: | note 100557 added to function.pcntl-fork | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-173391@lists.php.net to get a copy of this message | ||
"Fatal Error" has always been the bane of my world because there is no way to capture and
handle the condition in PHP. My team builds almost everything in PHP in order to leverage our core
library of code, so it was of the essence to find a solution for this problem of scripts bombing
unrecoverably and us never knowing about it.
One of our background automation systems creates a "task queue" of sorts and for each task
in the queue, a PHP module is include()ed to handle the task. Sometimes however a poorly behaved
module will nuke with a Fatal Error and take out the parent script with it.
I decided to try to use pcntl_fork() to isolate the task module from the parent code, and it seems
to work: a Fatal Error generated within the module makes the child task bomb, and the waiting parent
can simply catch the return code from the child and track/alert us to the problem as needed.
Naturally something similar could be done if I wanted to simply exec() the module and check the
output, but then I would not have the benefit of the stateful environment that the parent script has
so carefully prepared. This allows me to keep the child process within the context of the
parent's running environment and not suffer the consequences of Fatal Errors stopping the task
queue from continuing to process.
Here is fork_n_wait.php for your amusement:
<?php
if (! function_exists('pcntl_fork')) die('PCNTL functions not available on this PHP
installation');
for ($x = 1; $x < 5; $x++) {
switch ($pid = pcntl_fork()) {
case -1:
// @fail
die('Fork failed');
break;
case 0:
// @child: Include() misbehaving code here
print "FORK: Child #{$x} preparing to nuke...\n";
generate_fatal_error(); // Undefined function
break;
default:
// @parent
print "FORK: Parent, letting the child run amok...\n";
pcntl_waitpid($pid, $status);
break;
}
}
print "Done! :^)\n\n";
?>
Which outputs:
php -q fork_n_wait.php
FORK: Child #1 preparing to nuke...
PHP Fatal error: Call to undefined function generate_fatal_error() in ~fork_n_wait.php on line 16
FORK: Parent, letting the child run amok...
FORK: Child #2 preparing to nuke...
PHP Fatal error: Call to undefined function generate_fatal_error() in ~/fork_n_wait.php on line 16
FORK: Parent, letting the child run amok...
FORK: Child #3 preparing to nuke...
PHP Fatal error: Call to undefined function generate_fatal_error() in ~/fork_n_wait.php on line 16
FORK: Parent, letting the child run amok...
FORK: Child #4 preparing to nuke...
PHP Fatal error: Call to undefined function generate_fatal_error() in ~/fork_n_wait.php on line 16
FORK: Parent, letting the child run amok...
Done! :^)
----
Server IP: 64.71.164.2
Probable Submitter: 99.57.189.177
----
Manual Page -- http://www.php.net/manual/en/function.pcntl-fork.php
Edit -- https://master.php.net/note/edit/100557
Del: integrated -- https://master.php.net/note/delete/100557/integrated
Del: useless -- https://master.php.net/note/delete/100557/useless
Del: bad code -- https://master.php.net/note/delete/100557/bad+code
Del: spam -- https://master.php.net/note/delete/100557/spam
Del: non-english -- https://master.php.net/note/delete/100557/non-english
Del: in docs -- https://master.php.net/note/delete/100557/in+docs
Del: other reasons-- https://master.php.net/note/delete/100557
Reject -- https://master.php.net/note/reject/100557
Search -- https://master.php.net/manage/user-notes.php