ID: 39809 User updated by: e at osterman dot com Reported By: e at osterman dot com Status: Open Bug Type: CGI related Operating System: FC6 PHP Version: 5.2.0 New Comment:
Reproduce Code: <? // test-fcgi.php - a sample FCGI client define('FCGI_VERSION_1', 1); define('FCGI_BEGIN_REQUEST', 1); define('FCGI_ABORT_REQUEST', 2); define('FCGI_END_REQUEST', 3); define('FCGI_PARAMS', 4); define('FCGI_STDIN', 5); define('FCGI_STDOUT', 6); define('FCGI_STDERR', 7); define('FCGI_DATA', 8); define('FCGI_GET_VALUES', 9); define('FCGI_GET_VALUES_RESULT', 10); define('FCGI_RESPONDER', 1); define('FCGI_KEEP_CONN', 1); function FCGI_Packet($type, $content) { $len=strlen($content); $packet=chr(FCGI_VERSION_1).chr($type).chr(0).chr(1).chr((int)($len/256)).chr($len%256).chr(0).chr(0).$content; return($packet); } function FCGI_NVPair($name, $value) { $nlen = strlen($name); $vlen = strlen($value); if ($nlen < 128) $nvpair = chr($nlen); else $nvpair = chr(($nlen >> 24) | 0x80) . chr(($nlen >> 16) & 0xFF) . chr(($nlen >> 8) & 0xFF) . chr($nlen & 0xFF); if ($vlen < 128) $nvpair .= chr($vlen); else $nvpair .= chr(($vlen >> 24) | 0x80) . chr(($vlen >> 16) & 0xFF) . chr(($vlen >> 8) & 0xFF) . chr($vlen & 0xFF); return $nvpair . $name . $value; } function FCGI_Decode($data) { if( strlen($data) < 8 ) die("Packet too small " . strlen($data) . "\n"); $length = (ord($data{4}) << 8)+ord($data{5}); $packet = Array( 'version' => ord($data{0}), 'type' => ord($data{1}), 'length' => $length, 'content' => substr($data, 8, $length) ); return $packet; } function FCGI_Connect($host, $port) { // Connect to FastCGI server $socket = fsockopen($host, $port, $errno, $errstr, 5); if( !$socket ) die("Failed to connect to $host:$port\n"); return $socket; } function FCGI_Test($socket) { // Begin session $packet = ''; $packet .= FCGI_Packet(FCGI_BEGIN_REQUEST, chr(0).chr(FCGI_RESPONDER).chr(FCGI_KEEP_CONN).chr(0).chr(0).chr(0).chr(0).chr(0) ); // Build params $params = ''; $params .= FCGI_NVPair('GATEWAY_INTERFACE', 'FastCGI/1.0'); $params .= FCGI_NVPair('REQUEST_METHOD', 'GET'); $params .= FCGI_NVPair('SCRIPT_FILENAME', '/tmp/test.php'); $packet .= FCGI_Packet(FCGI_PARAMS, $params); $packet .= FCGI_Packet(FCGI_PARAMS, null); $packet .= FCGI_Packet(FCGI_STDIN, null); fwrite($socket, $packet); } function FCGI_Response($socket) { // Read answers from fastcgi server while(true) { if(feof($socket)) die("Socket closed\n"); $packet = fread($socket, 8); if( $packet === false ) die("Read failed\n"); $header = FCGI_Decode($packet); //print_r($header); $len=$header['length']%8; $padlen=($len?(8-$len):0); $packet .= fread($socket, $header['length']+$padlen); $response = FCGI_Decode($packet); if( $response['type'] == FCGI_END_REQUEST ) break; else print "[{$response['type']}] [{$response['content']}]\n"; } } $socket1 = FCGI_Connect('localhost', 1234); FCGI_Test($socket1); FCGI_Response($socket1); $socket2 = FCGI_Connect('localhost', 1234); FCGI_Test($socket2); FCGI_Response($socket2); ?> <? // /tmp/test.php - a sample cgi echo "Hello World\n"; ?> Then start php-cgi in single process mode. php-cgi -b 1234 Run test-fcgi.php. The second request will never return. If you only open up 1 socket, and run multiple requests it works fine. Previous Comments: ------------------------------------------------------------------------ [2006-12-13 03:27:22] e at osterman dot com Description: ------------ Dimitry states in bug #37422: > The "indle timeout" error is not a bug. It may occur > on high load, then requests concurrency is larger > then number of running PHP processes. This is the incorrect behavior and makes it impossible to detect when php-cgi is taking forever or simply ignoring you. According to the FastCGI specification, when the server is overloaded (e.g. connections exceed PHP_FCGI_CHILDREN), it should respond with FCGI_END_REQUEST packet with the protocolStatus flag of FCGI_OVERLOADED. The current behavior is php-cgi accepts the request, but never responds -- simply discarding it. It would be much better if PHP responded with FCGI_OVERLOADED, or simply rejected connections when it is too busy. http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S5.5 Reproduce code: --------------- To reproduce, open up more than PHP_FCGI_CHILDREN connections to the php-cgi server. All connections will be accepted and all will accept packets, but only PHP_FCGI_CHILDREN of the connections will ever return a response. The rest of the connections will simply accept the request and do nothing. Expected result: ---------------- Server should respond with FCGI_END_REQUEST packet with the protocolStatus flag of FCGI_OVERLOADED or simply reject connections when connections exceed PHP_FCGI_CHILDREN. Actual result: -------------- php-cgi never responds; request is lost. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=39809&edit=1