PHP で forkするときの注意点

以下のコードは子プロセスの終了時に親プロセスのMySQL接続が閉じられてしまうため意図した通りに動作しません。
子プロセスで明示的に mysql_close を行わなくても php プロセスの終了時の後処理で暗黙的に mysql_close されてしまうためです。

SIGTERM などで自分自身を強制終了させれば後処理が行われないので大丈夫です・・・実用性は皆無ですが・・・

<?
$conn = mysql_connect("localhost", "****", "****") or dir(mysql_error());

$pid = pcntl_fork();

if($pid < 0)
{
	exit;
}
else if($pid)
{
	// 親プロセス
	
	// 子プロセスの終了を待つ
	pcntl_waitpid(-1, $status, WUNTRACED);
	
	$sql = "SELECT 1";
	$res = mysql_query($sql, $conn) or die(mysql_error($conn));
	$row = mysql_fetch_assoc($res);
	
	var_dump($row);
}
else
{
	// 子プロセス
	
	exit;
	//user_error("", E_USER_ERROR);
	//posix_kill(posix_getpid(), SIGTERM);
}

PHPでforkするときは、出来るだけリソースを持っていない状態にしておいた方がよさそうです。

ストリームリソースの場合は子プロセスで fclose されても大丈夫ですが、fork の前に必ず flash しておくべきです(書き込みがバッファされている状態で fork するとバッファまで複製されて、2重に書き込まれることがあるため)。


と、思っていたのですが PHP 5.3.1 以前だと fclose で flock が明示的に呼ばれているらしいので問題になるケースもあります。

PHP 5.3.1 以前では fclose で明示的にアンロックされてしまう - ngyukiの日記