2011-07-14 3 views
6

クライアントがブラウザを閉じた場合(このようにサーバーへの接続)、このダミースクリプトがイベントを実行し続けるのはなぜですか?ブラウザ出口でPHPスクリプトが終了しない

 
while (true) 
{ 
    sleep(1); 
    file_put_contents('/tmp/foo' , "I'm alive ".getmypid()."\n" , FILE_APPEND); 
} 

thisによると予期せぬことです。またthisの例はうまくいかないようです。

set_time_limitゼロ以外のパラメータを指定すると、何も行われません。

私はいくつかの説明をしたいと思います。

+0

クライアントへの出力を一切行わずにユーザーの中止を無視しています。 – hakre

答えて

9

という出力をそのループ内のブラウザに書き込もうとすると、接続が終了した場合にスクリプトが異常終了することがわかります。この動作は、コマンドラインスクリプトとしてPHPを実行している場合ignore_user_abort

のドキュメントでを示唆し、スクリプトのTTYは、スクリプトは、それが書き込もうと 次の時間が死んでしまうスクリプトが終了されることなく、離れ を移行します値がTRUE

に設定されていないものは、私はいくつかの実験を自分で試してみました、そしてあなたには、いくつかのブラウザの出力をしようとしない場合でも、出力バッファがまだ満杯でない場合、スクリプトは動作し続けますことを見出しました。出力バッファリングをオフにすると、出力が試行されるとスクリプトは中止されます。これは理にかなっています。SAPIレイヤーは、出力を送信しようとしたときに要求が終了したことを認識する必要があります。ここで

はアボートをトリガ何実証例...

//ensure we're not ignoring aborts.. 
ignore_user_abort(false); 

//find out how big the output buffer is 
$buffersize=max(1, ini_get('output_buffering')); 


while (true) 
{ 
    sleep(1); 

    //ensure we fill the output buffer - if the user has aborted, then the script 
    //will get aborted here 
    echo str_repeat('*', $buffersize)."\n"; 

    file_put_contents('/tmp/foo' , "I'm alive ".getmypid()."\n" , FILE_APPEND); 
} 

です。出力なしの無限ループに入る可能性のあるスクリプトがある場合は、connection_aborted()を使用して、接続がまだ開いているかどうかをテストできます。

+0

同じことを試しました。 – cYrus

+0

@cYrus:何を試しましたか?あなたの質問のコードに反映させてください。無視するユーザーの中止を無効にする必要があります。デフォルト設定はIIRCです。 – hakre

+0

@Paul:作業コードを提供できますか? – cYrus

1

set_time_limitは、PHPコードで費やされる時間を制限します。あなたのプログラムのほとんどの時間(私は> 99.9%)はシステムコール、ファイルへのデータの書き込み、スリープに費やされます。あなたが(ないローカルファイルに)クライアントに何かを書いているとき

ignore_user_abortは中止されます - クライアントがexcplicitely接続を終了しない限り、あなたは、TCPにそれ以外の場合は未使用と終端接続を区別することができる方法は、単純にありませんRSTパケットで送信する。

+0

それは 'set_time_limit'について説明しています。何かを書いても変更はありません。 – cYrus

+0

*出力*への書き込みは、ユーザがIIRCを停止するのをトリガするために必要です。 - http://www.php。net/manual/en/features.connection-handling.php – hakre

+0

@hakreもちろん、ランダムなローカルファイルはTCP接続に影響しません。更新しました。 – phihag

関連する問題