Note: this is the same as this SO post, but is possibly more appropriate here as I suspect the problem is server config related rather than code related.
I'm using a LAMP setup with PHP running through
mod_fcgid. For most requests this works well, but I've noticed that when I download a file but interrupt the download before it's complete, the php-cgi process that was serving the file blocks attempting to write more data until it the
IPCCommTimeout is reached. Once the timeout is reached, the process gets interrupted and the process starts servicing other requests again.
This problem does not occur if I use
mod_php instead of
Is there some available setting for fcgid that I can set to have it abort if nothing is capturing the output? Is there something I can do in PHP to handle it?
The problem doesn't occur if the download isn't interrupted; in fact, I only noticed it because I was trying to stream a FLV file using gddflvplayer, which seems to send a brief request to get the first few frames (which it shows as a preview), then another to play it, and this causes the same problem.
FYI, this is the strace of the hanging cgi process; it sits like this until it's eventually interrupted, presumably by the process manager when the
IPCCommTimeout is reached. My guess is that it's hanging trying to output the results of the
readfile() call, but Apache is no longer listening (as the request has been cancelled by the user).
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
The logs indicate that the request is eventually reaped due to the timeout
mod_fcgid: read data timeout in 240 seconds
The download code more or less just uses
readfile to serve up the file, with a few headers involved as well (note: in this code,
Header is more or less just a wrapper around
header() to avoid problems in tests).
$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);
The server itself is running Debian Lenny with standard packages for
libapache2-mod-fcgid, but I also get the same results on a development box with Ubuntu 10.10.
Package information follows -
[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