php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #20033 Echoing/fputsing ~11k+ of data to STDOUT causes problem
Submitted: 2002-10-22 16:29 UTC Modified: 2003-01-02 18:38 UTC
From: ces at vaultbbs dot com Assigned:
Status: No Feedback Package: Sockets related
PHP Version: 4CVS-2002-10-22 OS: Red Hat 7.3
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2002-10-22 16:29 UTC] ces at vaultbbs dot com
I'm writing a POP3 server daemon in PHP.  Incoming requests to port 110 are routed to the POP3 server daemon by xinetd. Everything works fine if I *Telnet* to port 110.  Everything also works if I just run the script from the command line.

However, if I connect to my server by opening a true POP3 connection (such as from Eudora client), messages greater than about 11k cause problems when they are downloaded.  I originally suspected a POP3 implementation problem on my part.

However, I've confirmed that if I open a clean (non-Telnet) connection to my server and manually RETRieve the large message, the first 11k is dumped correctly but at about 11k everything else sent by PHP is garbage.

It appears as though there were some kind of output buffer overflow.  This also appears to damage the socket.  It does NOT cause the TCP/IP connection to be terminated, but no additional output is sent and the script becomes unresponsive to additional commands sent to it.

This *might* be related in some way to bug #19944 that I reported last week and which I closed this morning.

This is with snap 200210220900.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-10-22 16:34 UTC] ces at vaultbbs dot com
Additional info: If I switch my binary back to php 4.1.3, my POP3 server script works 100% inasmuch as this bug is concerned.  

Additionally, I can confirm that something is crashing in PHP in that if I dump data to a log file, the logfile ends where the data turns to garbage.  An additional log entry should be made when the message dump is complete.  This is never executed.

This is a weird problem that seems to cause PHP to hang, not core dump, and not terminate the TCP/IP connection but causes PHP to just dump garbage and just hang.
 [2002-10-22 16:57 UTC] wez@php.net
Can you isolate the line of code that causes the hang?
Use printf to output a note before each function you suspect of causing the problem; the last line output
by the script will tell you which one has hung.

We need to narrow it down to either sockets (as in ext/socket), or streams (fgets, fread, fwrite etc.),
or output buffer -- three unrelated areas.


 [2002-10-22 17:42 UTC] ces at vaultbbs dot com
Code I am using is:

while(ftell($mailfile) < $EndOfMessagePos)
{
 fputs($logfile, "Getting line\n");
 $line = fgets($mailfile, 4096);
 fputs($logfile, "Echoing line\n");
 echo "$line\r\n";
 $fst += strlen($line);
 fputs($logfile, "Sent $fst: $line\n");
 }
echo ".\r\n";
fputs($logfile, "Sent: CRLF\n");
fclose($logfile);

End of log file returns:
--START--
Getting line
Echoing line
Sent 11060: (unimportant email content)
Getting line
Echoing line
Sent 11147: (unimportant email content)
Getting line
Echoing line
--END--

Thus it appears to be hanging on the "echo" line.  

Again, this problem only presents itself when the script is running as a full server on a "clean" connection.  If the same exact test is run connecting via the telnet command to port 110 or by running the script from the command-line there is no problem.  It is my guess that the telnet command introduces some kind of flow control that is not present when I open a "real" POP3 connection to the same port.
 [2002-10-23 03:54 UTC] wez@php.net
It's more likely to be a problem with fgets; could you
try fflush($logfile) ing after the fputs lines, just to make sure that they're not waiting in the buffer.

Also, when php hangs, is it using a lot of CPU?

 [2002-10-23 06:26 UTC] msopacua@php.net
while(ftell($mailfile) < $EndOfMessagePos)

This line has the potential to cause a indefinete loop and there's no escape code in the loop, which breaks it.

ftell will return FALSE if an error occurs, which in numerical comparison resolves to 0.

Can you change that to:
while(ftell($mailfile) and ftell($mailfile) < $EndOfMessagePos)

 [2002-10-23 12:13 UTC] ces at vaultbbs dot com
I added requested fflush on $logfile after each fputs.  It still indicates that it is dying on the "echo".  I.e., logfile shows "Echoing line" but never reports "Sent."

Additional important correction: I'm not sure whether behavior has changed or if I was just wrong before, but when the problem presents itself the script IS shutting down and the TCP/IP connection IS disconnected.  In fact, it does so cleanly.  It executes my registered shutdown function.  In that function I had it write to the logfile and it shows that after the last "Echoing" line it DOES go through the shutdown function.  Connection_status() within the shutdown function reports "1" (aborted), but the client side definitely didn't request the abort.

I have also refined the loop so that the possible infinite loop situation is handled.  This is a welcome improvement to my code to handle an "impossible" situation (impossible because it is constrained elsewhere by logic) but it didn't have any effect on the current problem.
 [2002-10-23 16:07 UTC] wez@php.net
Does PHP eat a lot of CPU when it hangs?

Are you capable of running it under gdb and obtaining a backtrace?

make sure you are running an --enable-debug build of PHP.
gdb ./sapi/cli/php
run nameofyourscript.php
[hit CTRL-C when it hangs]
bt full

This would be ideal, because then we would know 100%
what was going on.

In light of your comments about shutdown, what happens if you comment out the fclose() line?

Also, what are your ini settings for output buffer related options? (and does changing those affect the problem?)

 [2002-11-06 12:29 UTC] ces at vaultbbs dot com
PHP doesn't eat a lot of cycles when it crashes.  As I corrected in a subsequent revision to the post, the connection is being closed and the script terminates--it even goes through the registered shutdown function as it terminates.  So no cycles are being eaten.

I've not used gdb.  I could, but I'm not sure if it is applicable in this case.  If I run the script from the command-line, it works fine.  If I run it by telneting into the port connected to the script, it works fine.  It only crashes if a raw (non-Telnet-based) connection is established to the script by, for example, Eudora mail client or by a test VB script that opens a raw connection without any potential telnet connection control.

As for output buffer options, I'm using the default php.ini. If you tell me what parameters specifically you'd like to know, I can look those up and/or change them.

Again, what surprises me is that it works in command-line, works when I connect to it as a daemon via Telnet, but it fails in the above-described manner when I connect to the same daemon but using a non-Telnet client; i.e., Eudora connects and fails.  If I write a custom VB app to just connect to the daemon to observe the problem, this fails as well.
 [2002-12-07 16:11 UTC] iliaa@php.net
Please try using this CVS snapshot:

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


 [2003-01-02 18:38 UTC] sniper@php.net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.


 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Mon Dec 06 18:03:34 2021 UTC