[PHP-users 25241] Re: cli をデーモンとして使用する際の注意

komura komura @ ma9.seikyou.ne.jp
2005年 4月 2日 (土) 02:47:33 JST


komura です。

On Thu, 31 Mar 2005 17:23:28 +0900
Ryuzo KOSAKI <kosaki @ fip.fujitsu.com> wrote:

> >どうやら、子プロセスの終了時に、データベースへの接続を解放してしまい、
> >次の接続が失敗してエラーが発生するようです。
> 
> fork()した場合、リソースも複製されるのでそれまでの接続が混乱
> してしまうことがあります(混乱というのはヘンですが、いい用語を
> 思い付かない)。
> ただ、子がDBMSと通信しているときに親は何もせず、子が終了する
> ときにmysql_close()のようなことをやらなければ、処理は続行でき
> るかもしれません。うまく行くときと行かないときの差はここにあ
> るのかも。

あまり深くは調べていませんので、間違っているかもしれませんが、
PHP のソースを変更せずに、子プロセスの終了時に DBMS との接続を
閉じないようにする方法はないような気がします。

PostgreSQL で試したところでは、持続的接続(pg_pconnect) を使用
しても、子プロセスの終了時に接続を閉じてしまうようです。


> socket通信を行なう典型的なサーバのプログラムだとこんな感じに
> やっています。
> 
> while (TRUE) {
>   $soc2 = stream_socket_accept($soc); //connect待ち
>   // エラー処理省略
>   $pid = pcntl_fork();
>   if ($pid === -1) {
>     die("pcntl_fork() error);
>   }
>   elseif ($pid) {
>     // 親は新しいsocketをcloseして待ちに戻る
>     fclose($soc2);
>     continue;
>   }
>   else {
>     fclose($soc);
>     // $soc2に対する子プロセスのいろんな処理
>     exit(0);
>   }
> }
> // ※子プロセスの処理は pcntl_signal() のハンドラで
> //  pcntl_waitpid()を実行
> 
> この場合でも、$soc2のIDは増え続けるんですね。リソースは開放
> されていたとしても、ちょっと、キモチ悪い。

確かにそうなりますね。

socket 通信としては一般的ではないと思いますが、以下のように
子プロセスで接続を待つようにすると $soc2 の ID は増えないようです。
PHP 5.0.3 で確認しました。
少し試した感じでは大きな問題はなさそうでしたが、実用できるかどうか
は分かりません。

$sock = stream_socket_server( 'tcp://127.0.0.1:10000', $errno, $errstr );
while ( TRUE ) {
  $pid = pcntl_fork();
  if ( $pid === -1 ) {
    exit;
  }
  else if ( $pid ) {
    pcntl_wait( $status );
  }
  else {
    $soc2 = stream_socket_accept( $sock );
    // エラー処理
    fclose( $sock );
    var_dump( $soc2 );
    fwrite( $soc2, date( 'Y/m/d H:i:s' ) . "\n" );
    fclose( $soc2 );
    exit( 0 );
  }
}

-- 
komura <komura @ ma9.seikyou.ne.jp>


PHP-users メーリングリストの案内