Observação: isso é o mesmo que esta postagem SO , mas é possivelmente mais apropriado aqui, pois suspeito que o problema esteja relacionado à configuração do servidor em vez de ao código.
Estou usando uma configuração LAMP com o PHP em execução em mod_fcgid
. Para a maioria das solicitações, isso funciona bem, mas notei que quando eu baixo um arquivo, mas o interrompo antes que ele seja concluído, o processo php-cgi que estava servindo os blocos de arquivo tenta gravar mais dados até atingir IPCCommTimeout
. Quando o tempo limite é atingido, o processo é interrompido e o processo começa a atender outras solicitações novamente.
Esse problema não ocorre se eu usar mod_php
em vez de mod_fcgid
.
Existe alguma configuração disponível para o fcgid que eu possa configurar para abortar se nada estiver capturando a saída? Existe algo que eu possa fazer no PHP para lidar com isso?
O problema não ocorre se o download não for interrompido; na verdade, eu só notei porque estava tentando transmitir um arquivo FLV usando o gddflvplayer, que parece enviar uma solicitação rápida para obter os primeiros quadros (que é exibido como uma prévia), depois outro para reproduzi-lo, e isso causa o mesmo problema.
FYI, esta é a sequência do processo cgi suspenso; fica assim até que seja eventualmente interrompido, presumivelmente pelo gerenciador de processos quando o IPCCommTimeout
é atingido. Meu palpite é que ele está pendurado tentando mostrar os resultados da chamada readfile()
, mas o Apache não está mais atendendo (já que a solicitação foi cancelada pelo usuário).
root@some-machine:~# strace -p 24837
Process 24837 attached - interrupt to quit
write(3, "|A3%76570621YjzD<2576:M2P5241"..., 17432
Os registros indicam que a solicitação é eventualmente obtida devido ao tempo limite
mod_fcgid: read data timeout in 240 seconds
O código de download mais ou menos usa apenas readfile
para exibir o arquivo, com alguns cabeçalhos envolvidos também (observação: neste código, Header
é mais ou menos apenas um wrapper em torno de 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);
O próprio servidor está executando o Debian Lenny com pacotes padrão para php5-cgi
, apache2
, libapache2-mod-fcgid
, mas eu também obtenho os mesmos resultados em uma caixa de desenvolvimento com o Ubuntu 10.10.
A informação do pacote segue -
[foo@bar ~]$ dpkg -l | egrep '(apache2|php5)'
ii apache2-mpm-worker 2.2.9-10+lenny9 Apache HTTP Server - high speed threaded model
ii apache2-utils 2.2.9-10+lenny9 utility programs for webservers
ii apache2.2-common 2.2.9-10+lenny9 Apache HTTP Server common files
ii libapache2-mod-fastcgi 2.4.6-1 Apache 2 FastCGI module for long-running CGI scripts
ii libapache2-mod-fcgid 1:2.2-1+lenny1 an alternative module compat with mod_fastcgi
ii php5 5.2.6.dfsg.1-1+lenny9 server-side, HTML-embedded scripting language (metapack
ii php5-cgi 5.2.6.dfsg.1-1+lenny9 server-side, HTML-embedded scripting language (CGI bina
ii php5-cli 5.2.6.dfsg.1-1+lenny9 command-line interpreter for the php5 scripting languag
ii php5-common 5.2.6.dfsg.1-1+lenny9 Common files for packages built from the php5 source
ii php5-curl 5.2.6.dfsg.1-1+lenny9 CURL module for php5
ii php5-ffmpeg 0.5.3.1-3 ffmpeg support for php5
ii php5-fileinfo 1.0.4-1 Fileinfo module for PHP 5
ii php5-gd 5.2.6.dfsg.1-1+lenny9 GD module for php5
ii php5-imagick 2.1.1RC1-1 ImageMagick module for php5
ii php5-mysql 5.2.6.dfsg.1-1+lenny9 MySQL module for php5
ii php5-suhosin 0.9.27-1 advanced protection module for php5