php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #24033 changed behaviour of fread() ?
Submitted: 2003-06-05 02:28 UTC Modified: 2003-06-13 18:20 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:0 (0.0%)
From: thomas at nimstad dot com Assigned:
Status: Not a bug Package: Sockets related
PHP Version: 4.3.2 OS: Win32
Private report: No CVE-ID: None
 [2003-06-05 02:28 UTC] thomas at nimstad dot com
Problem: 
fread() hangs if not reading exact number of bytes from a socket. worked previously in 4.3.1.

fread() returns max 1024 bytes even if specifying larger numbers. worked previously in 4.3.1.

Worked previously (snipped):
  $fp = fsockopen("localhost", 5410, $errno, $errstr, 100);
  // Send request
  if (!fputs($fp, $packet, strlen($packet))) { }

  // Read result header
  while (!feof($fp)) {
    $line = fgets($fp);

    if ($line != "\n" && $line != "\r\n") {
      $header .= $line;
    }
    else {
      if (preg_match('/Content-Length: (\d+)/i', $header, $matches))
        $length = $matches[1];

      if (preg_match('/X-Session-Id: (\d*)/i', $header, $matches))
        $session = $matches[1];
        
      break;
    }
  }

  // Read result body
  $reply = fread($fp, $length);

This hangs the executions until timeout (30 sec).

Have to change the read result body to:

  while (!feof($fp) && $length > 0) {
    $size = min(1024, $length);
    $reply .= fread($fp, $size);
    $length -= $size;
  }

All examples in documentation and even the PEAR/XML-RPC class states the "old" way what it looks to me.

What's up? New settings that i'm not aware of?

/Thomas

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-06-05 02:45 UTC] derick@php.net
Can you please tell us where in the documentation this is done wrong?
 [2003-06-05 02:56 UTC] thomas at nimstad dot com
I don't think it's a documentation problem of fread().

The posted code worked fine in 4.3.1 but failed when upgrading to 4.3.2 (Win32 version).

Problem 1: fread($fp, 4096) returns max 1024 bytes.
Problem 2: fread($fp, 1024) hangs until timeout if buffer only contains 1023 bytes.

/Thomas
 [2003-06-05 14:56 UTC] PJ at Elitegamer dot com
I too am experiencing this changed behavior. Previously, my code was as follows:

     $contents = fread ($fp, 2097152);

And that would return up to 2mb from the given socket. In my case, the socket was a fopen() url.
  
However, when I upgraded to PHP 4.3.2 it would ONLY return 2481 bytes no matter what. As a quick fix I had to move the fread() inside of a while loop, in order to fix this issue. Like this:

     $contents = "";
     while (($data = fread ($fp, 2097152)) !== "") 
     {
          $contents .= $data;
     }

The only change on my system and the files being read was my upgrading to PHP 4.3.2. This definitely appears to be changed behavior of fread().
-PJ
 [2003-06-06 01:46 UTC] philip@php.net
From the manual:

When reading from network streams or pipes, such as those returned when reading remote files or from popen() and proc_open(), reading will stop after a packet is available. This means that you should collect the data together in chunks as shown in the example below.

A bug existed in 4.3.0-1 that made it "work", so, it's not considered changed behavior, just a bug.  This bug, for example, did not exist in 4.2.3

Regarding Thomas "problem #2", not sure about that, will see what Wez has to say.

Regarding the last proposed example by PJ, just use file_get_contents().

 [2003-06-06 03:06 UTC] thomas at nimstad dot com
Ok. Since I'm was not the only having the problem I examined it some more... here we goes again...

Problem #1: When using a chunk size >= 8192 bytes it's just to concatenate the data and continue reading (as examplified in the documentation). So to what I understand, this is not a bug, rather than a timing issue that fread() returns the number of bytes available at the moment? Anyway, in this case problem #2 doesn't occurs!!

Problem #2: The fread() still hangs until timeout if I try to read data in chunks of <= 4096 bytes!!
 [2003-06-06 03:17 UTC] wez@php.net
This is your loop:

  while (!feof($fp) && $length > 0) {
    $size = min(1024, $length);
    $reply .= fread($fp, $size);
    $length -= $size;
  }

It looks wrong to me, since you are not checking the return value of fread and are just assuming that it read the chunk you asked for.

This is a better loop:

while ($length > 0) {
   $size = min(8192, $length);
   $data = fread($fp, $size);
   if (strlen($data) == 0) {
       break; // EOF
   }
   $reply .= $data;
   $length -= strlen($data);
}

It is recommended that you fread() in chunks of 8kb from sockets, as you will get better performance than using a smaller value.  Using a larger value is wasteful as the streams layer will only allocate in 8KB chunks; Win32 has a maximum internal packet size of 8KB too.

I'm marking this as bogus since it is the expected behaviour of PHP (I actually spent a couple of days correcting and testing this for HTTP/1.1 keep alives).

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 05:01:29 2024 UTC