note 99350 added to function.pcntl-fork

From: Date: Thu, 12 Aug 2010 10:46:06 +0000
Subject: note 99350 added to function.pcntl-fork
Groups: php.notes 
Request: Send a blank email to php-notes+get-171597@lists.php.net to get a copy of this message
you should be _very_ careful with using fork in scripts beyond academic examples, or rather just avoid it alltogether, unless you are very aware of it's limitations. the problem is that it just forks the whole php process, including not only the state of the script, but also the internal state of any extensions loaded. this means that all memory is copied, but all file descriptors are shared among the parent and child processes. and that can cause major havoc if some extension internally maintains file descriptors. the primary example is ofcourse mysql, but this could be any extensions that maintains open files or network sockets. also, just reopening your connection in the parent or child isn't a safe method, because when the old connection resource is destroyed, the extension might not just close it, but for example send a request to the server to log off, making the connection unusable. this happens with mysql for example, when php exits - in the following script the query will always fail with "MySQL server has gone away": <? mysql_connect(/* enter a working server here maybe? */); if(pcntl_fork()) die(); // fork a child and have the parent terminate //if(pcntl_fork()) posix_kill(getmypid(),9); // works, but very ugly $r=mysql_query("select 1;"); if(!$r)die(mysql_error()."\n"); ?> (it was suggested below that processes kill themselves with SIGKILL to avoid any cleanup on shutdown) (the only save way would be to close all connections and reopen them after the fork, and even that might not be possible if an extension keeps one open internally) for a nice demonstration of the havoc fork can create, try the below script. it opens a mysql connection, then forks, and runs queries from both parent and child, verifying that it receives the correct result. run it (on the cli preferably) a few times, and you will find various possible results: - very often is just hangs and doesn't output anything anymore - also very often, the server closes the connection, probably because it receives interleaved requests it can't process. - sometimes one process gets the result of the OTHER processes' query! (because both send their queries down the same socket, and it's pure luck who gets the reply) <? mysql_connect(/* enter a working server here maybe? */); $f=pcntl_fork(); while(true){ sleep(rand(0,10)/100); $r=mysql_query("select $f;"); if(!$r)die($f.": ".mysql_error()."\n"); list($x)=mysql_fetch_array($r); echo ($f)?".":"-"; if($x!=$f) echo ($f.": fail: $x!=$f\n "); } ?> ---- Server IP: 212.124.37.9 Probable Submitter: 62.132.24.17 ---- Manual Page -- http://www.php.net/manual/en/function.pcntl-fork.php Edit -- https://master.php.net/note/edit/99350 Del: integrated -- https://master.php.net/note/delete/99350/integrated Del: useless -- https://master.php.net/note/delete/99350/useless Del: bad code -- https://master.php.net/note/delete/99350/bad+code Del: spam -- https://master.php.net/note/delete/99350/spam Del: non-english -- https://master.php.net/note/delete/99350/non-english Del: in docs -- https://master.php.net/note/delete/99350/in+docs Del: other reasons-- https://master.php.net/note/delete/99350 Reject -- https://master.php.net/note/reject/99350 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#171597) next »