|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2008-12-21 16:03 UTC] 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
...
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 09:00:01 2025 UTC |
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) = 0Here's a test case: ----------------- TestServer.java ------------------ import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class TestServer { public static void main(String args[]) throws Exception { ServerSocket ss = new ServerSocket (9090); System.out.println("accepting connections"); Socket s = ss.accept(); System.out.println("got initial request"); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); while (true) { out.write((byte)in.read()); out.flush(); System.out.println("waiting for next request"); } } } ---------TestClient.php-------------- <?php function dieWithMsg() { var_dump(error_get_last()); exit(1); } $errno = null; $errstr = null; $conn = pfsockopen("127.0.0.1", 9090, $errno, $errstr, 30) or dieWithMsg(); fwrite($conn, "\0") or dieWithMsg(); fread($conn, 1) or dieWithMsg(); echo "done"; exit(0); ?> ------------------------------------ To reproduce this bug on Windows XP and above, start the server with: java TestServer and refresh the http://127.0.0.1/TestClient.php a few times. Then stop TestServer and start it again. Refresh http://127.0.0.1/TestClient.php to get a broken connection from PHP. I was able to reproduce this bug with yesterday's 5.2 windows snapshot. Regards, Jost B?kemeierUsing the test above I get: array(4) { ["type"]=> int(8) ["message"]=> string(112) "fwrite(): send of 1 bytes failed with errno=10054 Eine vorhandene Verbindung wurde vom Remotehost geschlossen. " So the bug is still there, I think. pfsockopen should transparently check the socket error code and allocate a new connection if the previous persistent connection has an error. I have tested this on Win XP and PHP 5.2.11 download.Err, 5.2.11 still uses the old code, doesn't it? With 5.3dev, Build Date Oct 26 2009 13:56:57, I get: array(4) { ["type"]=> int(2) ["message"]=> string(346) "fwrite(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Paris' for '1.0/no DST' instead" ["file"]=> string(89) "C:\Programme\Apache Software Foundation\Tomcat 6.0\webapps\JavaBridgeTemplate554\test.php" ["line"]=> int(11) }