ダウンロードが中断されると PHP + Fcgid がハングする

ダウンロードが中断されると PHP + Fcgid がハングする

注記:管理者の皆様、ServerFault への移行に投票してください。

私は LAMP セットアップを使用しており、PHP は を介し​​て実行されていますmod_fcgid。ほとんどのリクエストではこれでうまく機能しますが、ファイルをダウンロードしたがダウンロードが完了する前に中断すると、ファイルを提供していた php-cgi プロセスが、 に達するまでデータの書き込みをブロックすることに気づきましたIPCCommTimeout。タイムアウトに達すると、プロセスは中断され、プロセスは再び他のリクエストの処理を開始します。

出力をキャプチャするものが何もない場合に中止するように設定できる、fcgid の設定はありますか? PHP でこれを処理するために何かできることはありますか?

ダウンロードが中断されなければ、この問題は発生しません。実際、私がこれに気付いたのは、gddflvplayer を使用して FLV ファイルをストリーミングしようとしていたときでした。gddflvplayer は、最初の数フレームを取得するために短い要求を送信し、次にそれを再生するために別の要求を送信するようで、これによって同じ問題が発生します。

参考までに、これはハングしている CGI プロセスの strace です。最終的に中断されるまで、おそらくは にIPCCommTimeout達したときにプロセス マネージャーによって中断されます。私の推測では、呼び出しの結果を出力しようとしているためにハングしていますreadfile()が、Apache はリッスンしていません (ユーザーによって要求がキャンセルされているため)。

root@some-machine:~# strace -p 24837
Process 24837 attached - interrupt to quit
write(3, "\5|A\313%\35\337\376\275\237\230\266\242\371\37YjzD<\322\215\357\336:M\362P\335\242\214\341"..., 17432

ログには、タイムアウトによりリクエストが最終的に回収されたことが示されています。

mod_fcgid: read data timeout in 240 seconds

ダウンロード コードはreadfile、いくつかのヘッダーも含め、ファイルを提供する目的でのみ使用されます (注: このコードでは、テストでの問題を回避するためのHeaderラッパーにすぎませんheader())。

$filepath    = '/some/path/foo.flv';
$filename    = 'foo.flv';
$disposition = 'inline';

$h = Header::get();
$h->send('Pragma: public');
$h->send('Content-Transfer-Encoding: binary');
$h->send('Content-type: ' . FileSystem::get()->getMimeType($filepath));
$h->send('Content-Length: ' . FileSystem::get()->getFileSize($filepath));
$h->send('Content-Disposition: ' . $disposition . '; filename="' . $filename . '"');
$h->send('Content-transfer-encoding: 8bit');
$h->send('Expires: 0');
$h->send('Pragma: cache');
$h->send('Cache-Control: private');

flush();
readfile($filepath);

関連情報