php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #40556 Browser abort causes server hang with FastCGI
Submitted: 2007-02-20 12:10 UTC Modified: 2007-04-05 01:00 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: unreal at slashorg dot net Assigned: dmitry (profile)
Status: No Feedback Package: CGI/CLI related
PHP Version: 5.2.1 OS: Linux 2.6.18
Private report: No CVE-ID: None
 [2007-02-20 12:10 UTC] unreal at slashorg dot net
Description:
------------
PHP doesn't handle browser abort correctly.

- Use PHP to serve a file, using the code below
- Start downloading the file, and then abort.

Reproduce code:
---------------
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
header('Content-Disposition: attachment; filename="' . basename($path) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));
$handle = fopen($path, 'rb');
do {
	$data = fread($handle, 8192);
	if (strlen($data) == 0) {
		break;
	}
	echo($data);
} while (true);
fclose($handle);

Expected result:
----------------
After browser abord, the server should remain responsive.

Actual result:
--------------
* Lots of errors in error_log:
'FastCGI: comm with server "/usr/local/www/cgi/php-cgi/php5.fcgi" aborted: idle timeout (30 sec)'
'FastCGI: incomplete headers (0 bytes) received from server "/usr/local/www/cgi/php-cgi/php5.fcgi"'

* Server stops responding, then after some time (maybe 5 mins), starts responding again.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-02-20 12:14 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip


 [2007-02-20 12:48 UTC] unreal at slashorg dot net
I've just upgraded to 5.2.2-dev as you suggested, and that hasn't fixed the problem.

My server is still dying as soon as a connection gets aborted.
 [2007-02-21 15:18 UTC] dmitry@php.net
I am not able to reproduce the problem.

I tried to abort downloading from IE and download part of file running the following PHP script from command line:

<?php
$f = fopen("http://127.0.0.1/test/bug40556.php", "r");
$s = fread($f, 1024*1024);
var_dump($s);
fclose($f);
?>

both cases work fine (Apache-1.3.28 with mod_fastcgi or ZendEnabler on Linux 2.6.19)


 [2007-02-22 12:01 UTC] unreal at slashorg dot net
OK, I've done quite a lot more testing, and here are the results (Apache 2.0.59/mod_fastcgi 2.4.2/PHP 5.2.1):

- I cannot reproduce the bug with your code either.

- The following code causes PHP workers to lock up if you abort during download (and only if you abort):

             http://www.slashorg.net/ex/crash.txt

Note: notice the "session_start();" line

- If I remove the "session_start();" line, PHP doesn't crash anymore, even when I abort the download.


It seems this bug is more complicated than I thought, I hope you'll be able to reproduce it.

Thanks for your help.
 [2007-03-02 10:14 UTC] dmitry@php.net
I am still not able to reproduce the problem.
Could you please attach debugger to stuck php process and show its backtrace.
 [2007-03-06 13:27 UTC] unreal at slashorg dot net
Hello,

I haven't really used gdb before, I obtain a backtrace? I guess I have to recompile php with debug support?

Thanks.
 [2007-03-23 10:11 UTC] tony2001@php.net
>I guess I have to recompile php with debug support?
Yes, rebuild with --enable-debug is required.
- start PHP/FastCGI with just one process (-processes 1) 
- figure out pid of PHP (ps afx | grep php or see Apache error_log)
- start gdb (just type gdb and enter), then type "attach <pid of php>", this way you'll attach to already running PHP process.
- type "continue" for the process to continue running.
- after that reproduce the problem and see if the process stops.
- if it does, type "backtrace" and paste the output here.
- if it doesn't we'll continue in the next post.

You can also create an account on the server, I'll try to reproduce it myself. 
 [2007-03-23 14:55 UTC] unreal at slashorg dot net
Here's a backtrace, tell me if this helps you:

(gdb) attach 1774
Attaching to process 1774.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ................ done
0x900101b7 in write ()
(gdb) backtrace
#0  0x900101b7 in write ()
#1  0x004007c4 in safe_write (req=0x0, buf=0xbffffeb4, count=0) at /home/unreal/compile/php-5.2.1/sapi/cgi/fastcgi.c:351
#2  0x00002095 in start ()
(gdb)
 [2007-03-23 15:29 UTC] unreal at slashorg dot net
Some more information:

The issue only seems to appear when the client abandons the connection without ending the http session properly. For example, we have an antivirus gateway appliance that drops the connection with a tcp-reset when the browser cancels. PHP doesn't seem to get informed that the connection has ended and becomes non responsive until some timeout (?) occures. If I use "lsof" while the php process is blocked, I can see the process is still accessing the download file...
 [2007-03-28 08:44 UTC] tony2001@php.net
>Here's a backtrace, tell me if this helps you
The backtrace shows that write() syscall blocks when trying to write to an invalid socket.
Not something PHP can fix..
 [2007-04-05 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2014-12-05 19:28 UTC] dmanea28 at gmail dot com
Try calling 
session_write_close();
before reading the file.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 30 14:01:28 2024 UTC