php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #43782 feof() does not detect timeout on socket
Submitted: 2008-01-08 01:19 UTC Modified: 2010-01-10 23:38 UTC
Votes:8
Avg. Score:4.8 ± 0.7
Reproduced:8 of 8 (100.0%)
Same Version:3 (37.5%)
Same OS:3 (37.5%)
From: ml at foofree dot sk Assigned: kalle (profile)
Status: Closed Package: Documentation problem
PHP Version: 5.2,5.3CVS (2008-07-15) OS: *
Private report: No CVE-ID: None
 [2008-01-08 01:19 UTC] ml at foofree dot sk
Description:
------------
From docs:

"Returns TRUE if the file pointer is at EOF or an error occurs (including socket timeout); otherwise returns FALSE."

...

"If a connection opened by fsockopen() wasn't closed by the server, feof() will wait until a timeout has been reached to return TRUE. The default timeout value is 60 seconds. You may use stream_set_timeout() to change this value."



feof() dows not wait and returns TRUE instead of FALSE if timeout reached (server does not closed connection and there is no data in timeout time slot).

* server does not closed connection,
* timeout wa reached

Reproduce code:
---------------
$s = stream_socket_client('tcp://www.php.net:80', $errno, $errstr, 10, STREAM_CLIENT_CONNECT);

stream_set_timeout($s, 4);

$response = '';
while (feof($s) !== TRUE) {

   if (($foo = @fread($s, 1024 * 8)) === FALSE) return NULL;
   $response = $response . $foo;
};

print "OK";

Expected result:
----------------
prints "OK" approx. in 4 seconds

Actual result:
--------------
hangs forever

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-08-26 16:06 UTC] dsp@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 [2008-11-24 15:38 UTC] dsp@php.net
The patch was reverted as it caused problems. We might want to edit the documentation instead.
 [2008-11-27 14:17 UTC] x2012x at ymail dot com
From an end-user/developer standpoint, it would be preferred to have this issue addressed instead of just updating the documentation. 

Here's another real-world example of the issue being encountered.

Excerpt:
========
// Establish a socket connection with the designated host.
$_SESSION['socketCon'] = fsockopen($strHost, $strPort, $errNum, $errStr, $strTimeOut);
stream_set_blocking($_SESSION['socketCon'], 1);
stream_set_timeout($_SESSION['socketCon'], 3);
// Check to see if the socket connection could be established, if not display relevant error info.
if (!$_SESSION['socketCon'])
 {
   $errors .= "Cannot connect to socket!!!\r\n";
   $errors .= "Details:\r\n";
   $errors .= "Host: $strHost\r\n";
   $errors .= "Port: $strPort\r\n";
   $errors .= "Timeout value: $strTimeOut\r\n";
   $errors .= "Error #: $errNum\r\n";
   $errors .= "Response: $errStr\r\n";
   errorHandler($errors, "ERROR");
   stopTrans();
   $console->destroy();
   return 1;
 }
else
 {
   // Notify the user that a socket connection has been established.
   updateOutPut($console, $outPut, "Connected to $strHost on port $strPort\r");

   // Send the terminal transaction data over the established socket connection.
   updateOutPut($console, $outPut, "\rTransmitting: \r");
   updateOutPut($console, $outPut, "$sendingData ");
   fputs($_SESSION['socketCon'], $sendingData . "\n");       
		
   // Loop through the response from the server and print it to console.
   updateOutPut($console, $outPut,"\r\rResponse: \r");
   while(!feof($_SESSION['socketCon'])) 
    {
      $response = fgets($_SESSION['socketCon'], 4096);
      updateOutPut($console, $outPut, "$response");
    } 
   // Close the socket connection.
   fclose($_SESSION['socketCon']);
 }
========

If the socket server does not close the connection in the above !feof while loop, the function will get stuck looping in the while loop. It is my opinion that this sort of functionality ( a working timeout value ) is very fundamental. I've been using PHP for many years now and I am glad that this is the first bug that I've encountered to be major in my opinion. Please consider addressing the actual bug and not just modifying documentation. Thanks for your time.
 [2008-12-01 04:33 UTC] x2012x at gmail dot com
As a temporary work around, I've implemented a check against the socket responses and if the socket response is empty, I am assuming that the connection can be closed. This is certainly not the most desirable method and would not be needed if the socket timeout worked properly.

Workaround:
===========
// Establish a socket connection with the designated host.
$_SESSION['socketCon'] = fsockopen($strHost, $strPort, $errNum, $errStr,
$strTimeOut);
stream_set_blocking($_SESSION['socketCon'], 1);
stream_set_timeout($_SESSION['socketCon'], 3);
// Check to see if the socket connection could be established, if not
display relevant error info.
if (!$_SESSION['socketCon'])
 {
   $errors .= "Cannot connect to socket!!!\r\n";
   $errors .= "Details:\r\n";
   $errors .= "Host: $strHost\r\n";
   $errors .= "Port: $strPort\r\n";
   $errors .= "Timeout value: $strTimeOut\r\n";
   $errors .= "Error #: $errNum\r\n";
   $errors .= "Response: $errStr\r\n";
   errorHandler($errors, "ERROR");
   stopTrans();
   $console->destroy();
   return 1;
 }
else
 {
   // Notify the user that a socket connection has been established.
   updateOutPut($console, $outPut, "Connected to $strHost on port
$strPort\r");

   // Send the terminal transaction data over the established socket
connection.
   updateOutPut($console, $outPut, "\rTransmitting: \r");
   updateOutPut($console, $outPut, "$sendingData ");
   fputs($_SESSION['socketCon'], $sendingData . "\n");       
		
   // Loop through the response from the server and print it to
console.
   updateOutPut($console, $outPut,"\r\rResponse: \r");
   
   // WORKAROUND
   $resCheck = 0;
   while($resCheck == 0) 
    {
      $response = fgets($_SESSION['socketCon'], 4096);
      updateOutPut($console, $outPut, "$response");
      if ($response == '')
       {
         $resCheck = 1;
       }
    } 
   // Close the socket connection.
   fclose($_SESSION['socketCon']);
 }
===========
 [2009-03-19 02:53 UTC] mark at markparnell dot com dot au
I've just run into this same bug and agree that it would be much better fixed than just changing the documentation. It was causing threads to hang on the web server to the point that we were having to restart the server every 5 hours or it would run out of connections.

FWIW I've implemented a workaround for now like this:

	$hack_time = microtime(true);
	while(!feof($fp) && (microtime(true)-$hack_time) < 20){
		$string.=fgets($fp,128);
	}

Like x2012x's solution it's not ideal, but it's saved me for now.
 [2010-01-10 23:38 UTC] svn@php.net
Automatic comment from SVN on behalf of kalle
Revision: http://svn.php.net/viewvc/?view=revision&revision=293364
Log: Fixed bug #43782 (feof() does not detect timeout on socket)
 [2010-01-10 23:38 UTC] kalle@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.


 [2020-02-07 06:09 UTC] phpdocbot@php.net
Automatic comment on behalf of kalle
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=b4ceb970a7698a8290c4b4ff72dcd6ccad484d83
Log: Fixed bug #43782 (feof() does not detect timeout on socket)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Apr 20 03:01:28 2024 UTC