PHP + Fcgid зависает, если загрузка прерывается

PHP + Fcgid зависает, если загрузка прерывается

Примечание:Администраторы, пожалуйста, проголосуйте за переход на ServerFault.

Я использую настройку LAMP с PHP, работающим через mod_fcgid. Для большинства запросов это работает хорошо, но я заметил, что когда я загружаю файл, но прерываю загрузку до ее завершения, процесс php-cgi, обслуживающий файл, блокирует попытки записать больше данных, пока не будет IPCCommTimeoutдостигнуто время ожидания. После достижения тайм-аута процесс прерывается и снова начинает обслуживать другие запросы.

Есть ли какие-то доступные настройки для fcgid, которые я могу задать, чтобы он прерывался, если ничего не захватывает вывод? Можно ли что-то сделать в PHP, чтобы справиться с этим?

Проблема не возникает, если загрузка не прерывается; на самом деле, я заметил ее только потому, что пытался транслировать FLV-файл с помощью gddflvplayer, который, похоже, отправляет короткий запрос для получения первых нескольких кадров, а затем еще один для их воспроизведения, и это вызывает ту же проблему.

FYI, это след зависшего процесса cgi; он сидит так, пока его в конце концов не прервет, предположительно менеджер процессов, когда будет 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);

Связанный контент