MySQL テーブルを通過し、子プロセスを生成する「永遠の」プロセスが必要です。擬似コード:
while(true)
$rows = SELECT * FROM workers
foreach($rows as $row){
DELETE $row->id
spawn_child($row->id)
}
sleep(5)
}
function spawn_child($id){
$pid = pcntl_fork()
if($pid <0){
//err
}elseif($pid == 0){
//child
exec("worker_program $id");
exit();
}elseif($pid > 0){
//parent
}
}
問題は、子プロセスが worker_program から戻ってきて終了するときに、明らかに共有されている mysql ハンドルを閉じるため、親プロセスが「Msql server going away」エラーを受け取ることです。
これを解決するにはどうすればよいですか?設計ミスですか?
子が自由に終了できるように、dbリソースなどを共有せずに、PHPでプロセスを生成して切り離すにはどうすればよいですか?
(試してみました: setsid と fork を再度試しworker_program &
、php で fork する代わりに ' ' でワーカーを呼び出しましたが、まったく機能していないようです (変ですか?)。私は PDO を使用しています。php.net の人たちもこの動作はバグではないと言います. これは osx と php5.3 (および debian) にあります.)
参考文献:
php.net/bug: 「子プロセスがなくなった後、親プロセスが MySQLi 接続を失った」
更新/回避策
だから私はついにこれに対処する方法を見つけました。popen
機能するのは、ワーカープロセスを生成するために使用することです。そうすれば、共有なしで、完全に「新しい」プロセスが作成されたように見えます。次に、子供に分岐と切り離しをさせます。pcntl_fork
したがって、マスタープロセスでは、 orの代わりにexec
:
$p = popen("worker_program $arg","r");
sleep(1); //give it time to detach (won't work otherwise. Any other ideas?)
pclose($p);
そして、ワーカープログラムで:
#!/usr/bin/env php
<?php
//fully detach from parent, as proposed by the 'gurus'
//(Why can't this be done with only one fork?)
if(pcntl_fork()) {
exit();
}
posix_setsid();
if(pcntl_fork()) {
exit();
}
...