2

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();
}
...
4

3 に答える 3

2

永続的なMySQL接続を使用するのはどうですか。そして、完了したことがわかったら閉じます。

$conn = new mysqli("p:".$dbhost, $dbuser, $dbpass, $dbname);

$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass,
    array(PDO::ATTR_PERSISTENT => true));
于 2009-06-12T16:47:11.343 に答える
1

子で行われたときにdbハンドルの設定を明示的に解除して、子の終了時に閉じられない場合はどうでしょうか。親はハンドルリンクを保持する必要があるため、リンクが閉じられない可能性があります。

于 2009-06-12T17:44:30.520 に答える
0

それらのどれも私のために働いていませんでした。これは私がしました:

// php execl type behaviour, execute and leave ...
// the args may be passed to $command or $args
// ekerner@ekerner.com.au
function execl($command, $args = array())
{
  $command = escapeshellarg($command);
  foreach ($args as $arg)
    $command .= ' ' . escapeshellarg($arg);
  exec($command . ' 2>/dev/null >&- /dev/null &');
}
于 2011-05-01T16:38:35.233 に答える