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

Reply via email to