ID:               46917
 User updated by:  jost_boekemeier at users dot sf dot net
 Reported By:      jost_boekemeier at users dot sf dot net
-Status:           Feedback
+Status:           Open
 Bug Type:         Streams related
 Operating System: *
 PHP Version:      5.2.8
 New Comment:

Due to its nature (uninitialized variable) you may or may not be able
to reproduce this bug. See
http://sourceforge.net/mailarchive/forum.php?thread_name=828E3F73B78941EAB5AF3E2E07C37D8D%40IBM1020C944423&forum_name=php-java-bridge-users
for details.

However, you should immediately see the bug by looking at the PHP
source code: 

  0 == recv(sock->socket, &buf, sizeof(buf), MSG_PEEK

does NOT set errno (the result code is 0, not -1) so that errno
contains a bogus value, most likely the error code from a previously
failed sys call, so that

  php_socket_errno() != EAGAIN

fails, depending on the application's PHP code, as errno sometimes
contains EAGAIN (from a previous poll()).


Just search the PHP sources for the pattern


} else if (php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv)
>
0) {
 if (0 == recv(sock->socket, &buf, sizeof(buf), MSG_PEEK) &&
php_socket_errno() != EAGAIN) {
        alive = 0;
}


and set the errno or the lastErrorCode (for windows) to zero before
calling this pattern. 

After that persistent sockets, soap and a few other places will work
reliably.

There are a few caveats, however. First, if you pass the last error
number to application-level, you might have to restore the last errno
immediately after the recv call. Second, I don't know what the
php_socket_errno() != EAGAIN should do, anyway, as EAGAIN is only set
when the previous sys call failed (result code -1, not 0!). So I suggest
to ask the author to explain his/her code before fixing anything.


Regards,
Jost Bökemeier


Previous Comments:
------------------------------------------------------------------------

[2008-12-24 19:48:34] fel...@php.net

Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc. If the script requires a 
database to demonstrate the issue, please make sure it creates 
all necessary tables, stored procedures etc.

Please avoid embedding huge scripts into the report.



------------------------------------------------------------------------

[2008-12-21 16:07:15] jost_boekemeier at users dot sf dot net

The relevant part of the bug trace was missing. 

poll([{fd=16, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 1
([{fd=16, revents=POLLIN}])
recv(16, ""..., 1, MSG_PEEK)            = 0
send(16, "PUT /JavaBridge/JavaBridge.phpjavabridge HTTP/1.1\r\nHost:
localhost\r\nContent-Length: 40\r\nX_JAVABRIDGE_CHANNEL:
/dev/shm/.php_java_bridgexN2WsO\r\n\r\n\177C<H p=\"1\"
v=\"php.java.bridge.Util\"></H>"..., 185, 0) = 185
poll([{fd=16, events=POLLIN|POLLERR|POLLHUP}], 1, -1) = 1 ([{fd=16,
revents=POLLIN|POLLERR|POLLHUP}])
recv(16, ""..., 8192, 0)                = 0

------------------------------------------------------------------------

[2008-12-21 16:03:05] jost_boekemeier at users dot sf dot net

Description:
------------
PHP cannot handle broken socket connections due to an uninitialized
variable.

xp_socket.c and several other places contain the following pattern:

...
} else if (php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv)
> 0) {
 if (0 == recv(sock->socket, &buf, sizeof(buf), MSG_PEEK) &&
php_socket_errno() != EAGAIN) {
        alive = 0;
}
...

It is obvious that the above code cannot work on any operating system;
checking if the socket doesn't have an error and then asking for its
error code is simply nonsense.

The same pattern is used in several other places within PHP.


The above code fails constantly on Windows. On Linux/Unix a workaround
is to add the constant 1E512 to the PHP script, which initializes errno
with a value != EAGAIN.


Regards,
Jost Bökemeier




Reproduce code:
---------------
pfsockopen() 
...
// restart back end
...
pfsockopen()

=>



Expected result:
----------------
...

poll([{fd=16, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 1
([{fd=16, revents=POLLIN}])
recv(16, ""..., 1, MSG_PEEK)            = 0
close(16)    

...

Actual result:
--------------
...

poll([{fd=16, events=POLLIN|POLLERR|POLLHUP}], 1, -1) = 1 ([{fd=16,
revents=POLLIN|POLLERR|POLLHUP}])
recv(16, ""..., 8192, 0)                = 0
gettimeofday({1229844164, 46391}, NULL) = 0
write(2, "[Sun Dec 21 08:22:44 2008] [error] [client 127.0.0.1] PHP
Notice:  Undefined index:  content_length in 

...


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=46917&edit=1

Reply via email to