php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #25939 [PATCH] feof no longer detects connections closed by the server
Submitted: 2003-10-21 15:45 UTC Modified: 2003-11-28 17:10 UTC
From: mlemos at acm dot org Assigned:
Status: Closed Package: Sockets related
PHP Version: 4.3.4 OS: *
Private report: No CVE-ID:
 [2003-10-21 15:45 UTC] mlemos at acm dot org
Description:
------------
It seems that since the changes introduced after PHP 4.3.1, the feof function is no longer returning true when the server closes the socket connection after transmiting all the contents.

This seems to make it impossible to determine if there was a real network error or the server closed the connection normally breaking the compatibility of scripts that rely on feof to determine the end of connection condition.

Reproduce code:
---------------
The following script demonstrates the change of behaviour. You should try it either PHP versions before and after PHP 4.3.2 to see the difference.

<?php
 
        $socket=fsockopen("www.php.net",80,$error);
        if(!$socket)
        {
                echo "socket opening error\n";
                exit;
        }
        echo "connection opened\n";
        if(!fputs($socket,"GET / HTTP/1.1\r\nHost: www.php.net\r\n\r\n"))
        {
                echo "socket writing error\n";
                exit;
        }
        while(!feof($socket))
        {
                $data=fread($socket,1000);
                if(!$data)
                {
                        echo "socket reading error\n";
                        exit;
                }
                echo "read ",strlen($data)," bytes\n";
        }
        echo "reached the end of data\n";
        fclose($socket);
?>

Expected result:
----------------
connection opened
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 278 bytes
reached the end of data


Actual result:
--------------
connection opened
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 1000 bytes
read 278 bytes
socket reading error


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-11-11 00:44 UTC] mlemos at acm dot org
Actually there is a small bug in the patch. Here is the correct version:

*** network.c   2003-11-11 03:06:07.000000000 -0200
--- network.c.fixed     2003-11-10 18:41:16.000000000 -0200
***************
*** 1033,1038 ****
--- 1033,1049 ----
                nr_bytes = recv(sock->socket, buf, count, 0);
   
                stream->eof = (nr_bytes == 0 || (nr_bytes == -1 && php_socket_errno() != EWOULDBLOCK));
+
+               /*  We did not reach the end of data but it did not fill the buffer?
+                *  Maybe the server closed the connection. Lets peek ahead.
+                */
+               if (!stream->eof && (count - nr_bytes > 0)) {
+                       int more_bytes;
+
+                       more_bytes = recv(sock->socket, buf + nr_bytes, 1, MSG_PEEK);
+
+                       stream->eof = (more_bytes == 0 || (more_bytes == -1 && php_socket_errno() != EWOULDBLOCK));
+               }
        }
   
        if (nr_bytes > 0) {
 [2003-11-28 17:10 UTC] wez@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, 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/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.

Thanks for the patch; I used a slightly different technique to fix the problem, although the essence was very much the same, but moving the peek into feof() itself.
 [2004-04-26 19:36 UTC] topace at lightbox dot org
This bug fix causes another bug.  Im using Ilohamail 
(http://www.ilohamail.org) and after upgrading to PHP 
4.3.6, it would take several minutes to login to the 
webmail system.  The culprit I traced down to this 
function: 
 
function iil_ReadLine($fp, $size){ 
        $line=""; 
        if (($fp)&&(!feof($fp))){ 
                do{ 
                        $buffer = fgets($fp, 1024); 
                        $endID = strlen($buffer) - 1; 
                        $end = (($buffer[$endID] == "\n")||
(feof($fp))); 
                        $line.=$buffer; 
                }while(!$end); 
        } 
        if ((feof($fp)) && (!empty($line))) $line.="\n"; 
        return $line; 
} 
 
the final line before the return... the  feof($fp) is 
BLOCKING until a timeout occurs (several minutes).  The 
feof($fp) should definitely not BLOCK! 
 
Cheers, 
  James
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 15:01:54 2014 UTC