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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: thomas at nimstad dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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 Nov 26 18:01:33 2024 UTC