|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [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
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Thu Oct 30 18:00:02 2025 UTC | 
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.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']); } ===========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.