php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #37641 recv in fastcgi never returns when server doesn't pad to size of 8
Submitted: 2006-05-30 09:35 UTC Modified: 2006-06-09 00:35 UTC
From: roguestar191 at comcast dot net Assigned: dmitry (profile)
Status: Not a bug Package: CGI/CLI related
PHP Version: 5.1.4 OS: linux
Private report: No CVE-ID: None
 [2006-05-30 09:35 UTC] roguestar191 at comcast dot net
Description:
------------
line 624 of sapi/cgi/fastcgi.c contains:

while (recv(req->fd, buf, strlen(buf), 0) > 0) {}

with buf being an array with 8 elements.

With the server doesn't pad all packets to the size of 8 

(Which is suggested but not required by the fast-cgi spec), this causes frequent lockups and failed requests. (Without that padding, I have no idea about with it).

My fix was simple - change strlen(buf) (which returns 8), to 1, so it will read any excess bytes at the end and cleanly close and continue on, even if it's not a multiple of 8 bytes.  

Thank you for php!

Expected result:
----------------
fast-cgi padding to be read and thrown out, requests to close.

Actual result:
--------------
request tends to lock up on recv when packets arn't a multiple of 8 in size.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-05-30 09:37 UTC] roguestar191 at comcast dot net
sorry that should be "when the server doesn't pad all the packets to the size of 8"
 [2006-05-31 06:43 UTC] dmitry@php.net
I am not sure that the reason of problem is padding.
Seems fcgi module doesn't close connection.
Does it use FCGI_KEEP_CONN?
What web server and fcgi module do you use?

 [2006-05-31 11:41 UTC] roguestar191 at comcast dot net
I use a purely custom webserver and custom fcgi module, both hand written by me. 

I detected the problem by launching:
valgrind --tool=memcheck -v -v php-cgi -b 42000
Luanch my webserver
Luanch a web browser
Load a php page - Web browser never finish's loading
I press control+c in valgrind, it always outputs it was on:
fcgi_close_connection line 624/recv().

The only reason to "Read 8 bytes" at a time would be if padding were a multiple of 8 bytes, as suggest by:
http://www.fastcgi.com/devkit/doc/fcgi-spec.html

Quote: "We recommend that records be placed on boundaries that are multiples of eight bytes. The fixed-length portion of a FCGI_Record is eight bytes. "

Changing strlen(buf) to 1 is not a potential fix, it is a fix, and it works, I've already tested it.


At worst it will create 1-255 extra loops that do nothing except call recv() while recv still has things to return. (255 if the server pads with 255 bytes extra, which would be a total waste of bandwidth.)

At best it will allow webservers that don't pad to a multiple of 8 bytes to work properly - and not freeze on recv() waiting for data that will never show up.

The server isn't sending _anything_ special to the fcgi client app, it connects(), sends params, sends null on stdin(or post data), returns to the main select() function that returns ALL data from every single connection, waits for FCGI_END_REQUEST or for the socket to be closed, processing and buffering any FCGI_STDOUT data - sending stdout data at end_request. At end request it closes the socket - and prints to the client user whatever's left in the stdout buffer, runs a fast-cgi fifo (If two requests use the same fcgi program it fifo's them), or if FCGI_OVERLOADED or FCGI_CANT_MPX_CONN it will fifo the request.
 [2006-05-31 19:10 UTC] roguestar191 at comcast dot net
I've taken the time to create an ethereal dump of a first request - in case it's a problem with my server. it's possible I did something wrong but i don't see it. http://roguestar.dynu.com:5555/fcgidump (load with ethereal fcgidump).

This is a dump of a request to php and back to a www.pastebin.com running on my server. Php is on port 4444, my server is port 46588 in this case.
 [2006-06-08 11:52 UTC] dmitry@php.net
Your server/fastcgi_module should call shutdown() after sending FastCGI request to PHP (or close() after getting EOF from PHP).

In case of closed connection recv() should be interrupted.
 [2006-06-09 00:35 UTC] roguestar191 at comcast dot net
I'm very sorry, There were a two bugs in my server.

the strangest bug was the content-length field being generated as 0.. It's strange this zero content length didn't crop up until switching to 5.1.4 from 5.1.2.. Who knows.. My fault. Fixed. 

The other bug was with the http caching object running on post requests when obviously it shouldn't have. 

Again, very sorry. Thank for your time!
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue May 21 20:01:32 2024 UTC