
Observação:administradores, votem pela migração para ServerFault.
Estou usando uma configuração LAMP com PHP rodando em mod_fcgid
. Para a maioria das solicitações isso funciona bem, mas percebi que quando faço o download de um arquivo, mas interrompo o download antes de ser concluído, o processo php-cgi que estava servindo o arquivo bloqueia a tentativa de gravar mais dados até que seja IPCCommTimeout
alcançado. Quando o tempo limite é atingido, o processo é interrompido e começa a atender outras solicitações novamente.
Existe alguma configuração disponível para fcgid que eu possa definir para abortar se nada estiver capturando a saída? Existe algo que eu possa fazer em PHP para lidar com isso?
O problema não ocorre se o download não for interrompido; na verdade, só percebi isso porque estava tentando transmitir um arquivo FLV usando gddflvplayer, que parece enviar uma breve solicitação para obter os primeiros quadros e depois outra para reproduzi-lo, e isso causa o mesmo problema.
Para sua informação, este é o caminho do processo cgi suspenso; fica assim até ser eventualmente interrompido, provavelmente pelo gerenciador de processos quando IPCCommTimeout
for alcançado. Meu palpite é que ele está travando ao tentar gerar os resultados da readfile()
chamada, mas o Apache não está mais ouvindo (pois a solicitação foi cancelada pelo usuário).
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
Os logs indicam que a solicitação eventualmente é colhida devido ao tempo limite
mod_fcgid: read data timeout in 240 seconds
O código de download é mais ou menos usado apenas readfile
para servir o arquivo, com alguns cabeçalhos envolvidos também (nota: neste código, Header
é mais ou menos apenas um wrapper header()
para evitar problemas nos testes).
$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);