php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #23258 fgets() hangs 15 seconds on EOF of a socket
Submitted: 2003-04-17 07:35 UTC Modified: 2003-04-28 10:33 UTC
From: markus dot pfefferle at web dot de Assigned: wez (profile)
Status: Not a bug Package: Sockets related
PHP Version: 4.3.2-RC OS: Windows 2000
Private report: No CVE-ID: None
 [2003-04-17 07:35 UTC] markus dot pfefferle at web dot de
This well-known fragment of code takes up about 15 seconds on my machine:

<pre>
    $fp = fsockopen($host, $port);
    fputs($fp, "POST $path HTTP/1.1\n");
    fputs($fp, "Host: $host\n");
    fputs($fp, "Content-type: application/x-www-form-urlencoded\n");
    fputs($fp, "Content-length: ". strlen($data_to_send) ."\n");
    fputs($fp, "Connection: close\n\n");
    fputs($fp, "$data_to_send\n");

    while(!feof($fp)) {
      $res .= fgets($fp, 128);
    }
</pre>

In order to trace the cause fot this pause, I modified whie while-loop to give me some debugging information:

<pre>
    while(!feof($fp)) {
      $r = fgets($fp, 128);
      echo time()." : ".var_dump($r),"\n";
    }
</pre>

Truns out this on the final 3 lines:

<pre>
1050581993 : 
string(2) "
"
1050581993 : 
bool(false)
1050582009 : 
Array
</pre>

The second line that returned false should already have flipped the EOF flag on the connection, but apparently it didn't. The last call that finally flips this flag however takes up 15 seconds of time and returns (odd enough) an empty array.

Alrighty I think - if the false-value of the last chunk will give me a clue to break the loop, I just change my code to this:

<pre>
    do {
      $r = fgets($fp, 128);
      echo time()." : ".var_dump($r),"\n";
    } while ($r);
</pre>

And guess what - exactly the same 15 seconds, exactly the same output as before. The loop didn't even exit when $r was bool(false) according to var_dump(). This is what really puzzles me.

I also used fread and toyed around with any possible length-parameter. It's always these 15 seconds delay at the last read that returns this odd empty array.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-04-17 09:13 UTC] markus dot pfefferle at web dot de
The "Array" is a mistake actually - an output from another place of my code. Yet still the mystery remains, why the loop goes through another cycle after the last call to fgets() has returned false and feof() is not reflecting the end of the connection. And why $r in this case does not check out as "false" in an expression to preliminary end the loop.
 [2003-04-17 09:23 UTC] markus dot pfefferle at web dot de
Err, nevermind. I figured out why - var_dump() writes to the output buffer before echo does.

But in the end, the 15 second-problem remains. Here with fread($fp, 1):

1050589160 : string(1) "\n"
1050589160 : string(1) "\n"
1050589160 : string(1) "\n"
1050589160 : string(1) "\n"
1050589175 : string(0) ""

It takes fread() and fgets() in Blocking mode 15 seconds to realize that the connection has been severed.
 [2003-04-23 07:15 UTC] markus dot pfefferle at web dot de
Back from Eastern holiday.

Downloaded and installed the CVS snapshot (phpinfo() says build 2195) and tried it again.

Same error - 15 seconds pause at the last (failing) read from a socket:

1051099825 : string(1) ""
1051099825 : string(1) ""
1051099825 : string(1) ""
1051099825 : string(1) ""
1051099841 : string(0) ""

So ticket still open.
 [2003-04-25 05:44 UTC] wez@php.net
I must verify/fix this before 4.3.2 goes gold.
 [2003-04-28 08:07 UTC] wez@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php4-STABLE-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php4-win32-STABLE-latest.zip

I can't reproduce this here under winxp with the latest stable snapshot.

Does it work if you use the correct canonical line endings for your headers as specified by the HTTP spec ?
"\n" is incorrect, "\r\n" is correct.

 [2003-04-28 09:38 UTC] markus dot pfefferle at web dot de
Did as you said, used \r\n, but it makes no difference.

Webserver running is Apache 2.0.44

I will try to setup the same installation on a different platform tonight and get back on you about the result.
 [2003-04-28 10:33 UTC] markus dot pfefferle at web dot de
Oy! I managed to find the cause of this "bug" (and judging by some previous bug reports on here, an answer to all these):

It appears that the Windows distribution of the Apache webserver (2.0.44-46) totally ignores the 'Connection: close' line in the http header and keeps connections alive for a period of time dependent and provided by the Parameters

  KeepAlive On
  KeepAliveTimeout 15 (!!)

in its httpd.conf.

I did the same test directing the request below to an Apache server running under Linux, and with the Connection: close header field, the connection was seperated immediately - while without it: the same 15 second delay.

So while I thought that providing the "Connection: close" header should have cause an immediate disconnection of the webserver I tested this on, the connection was in fact kept alive all the time for these 15 seconds and therefore the delay with the last fread() operation.

So I flag this ticket 'Bogus', you may go gold now with the 4.3.2 (sorry for delaying) and I'll see if I can report this bug to the Apache Group :)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 23 19:01:31 2024 UTC