From: tiny_grasshopper at hotmail dot com Operating system: Win32 XP SP2 PHP version: 5.2.3 PHP Bug Type: Sockets related Bug description: client disconnect not detected by socket_select()
Description: ------------ I was working on aan abstraction layer for a multi threaded server. It was not till very late I noticed the following strange behaviour: I let a bunch of client connect. Lets say #1, #2 and #3. When I disconnect them (not gracefuly) in de backward order (#3, #2 then #1) every thing works as it should be; the 'Close' callback functions are called, and in the right order. However, when I disconnect them in the same order (#1, #2 then #3) the callback functions will not be called until the last client is closed. After further testing I noticed that all client closed will only be detected by socket_select if the latter clients are closed. Reproduce code: --------------- function Error($error, $desc) { echo "Error: $error - $desc\n"; } function Connect($id) { echo "#$id connected.\n"; } function Close($id) { echo "#$id closed.\n"; } function Receive($id, $msg) { echo "#$id said: $msg\n"; } //------------------------------------------------------------------------------ if (($listener = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == false) { Error("socket_create() failed", socket_strerror($listener)); exit; } socket_set_option($listener, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_nonblock($listener); if (($error = socket_bind($listener, '0.0.0.0', 23)) == false) { Error("socket_bind() failed", socket_strerror($error)); exit; } if (($error = socket_listen($listener, 5)) == false) { Error("socket_listen() failed", socket_strerror($error)); exit; } $sock = array($listener); //------------------------------------------------------------------------------ for (;;) { $read = $sock; socket_select($read, $write = NULL, $except = NULL, NULL); foreach($read as $socket) { if ($socket == $listener) { if (($client = socket_accept($listener)) == false) { Error("socket_accept() failed", socket_strerror($client)); continue; } else { $sock[] = $client; $index = intval($client); Connect($index); } } else { $bytes = @socket_recv($socket, $input, 512, 0); $index = intval($socket); if ($bytes == 0) { if (($key = array_search($socket, $sock)) !== false) unset($sock[$key]); socket_close($socket); Close($index); } else { Receive($index, $input); } } } } Expected result: ---------------- #5 connected. #6 connected. #7 connected. #5 closed. #6 closed. #7 closed. Actual result: -------------- #5 connected. #6 connected. #7 connected. #7 closed. #5 closed. #6 closed. -- Edit bug report at http://bugs.php.net/?id=42423&edit=1 -- Try a CVS snapshot (PHP 4.4): http://bugs.php.net/fix.php?id=42423&r=trysnapshot44 Try a CVS snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=42423&r=trysnapshot52 Try a CVS snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=42423&r=trysnapshot60 Fixed in CVS: http://bugs.php.net/fix.php?id=42423&r=fixedcvs Fixed in release: http://bugs.php.net/fix.php?id=42423&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=42423&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=42423&r=needscript Try newer version: http://bugs.php.net/fix.php?id=42423&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=42423&r=support Expected behavior: http://bugs.php.net/fix.php?id=42423&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=42423&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=42423&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=42423&r=globals PHP 3 support discontinued: http://bugs.php.net/fix.php?id=42423&r=php3 Daylight Savings: http://bugs.php.net/fix.php?id=42423&r=dst IIS Stability: http://bugs.php.net/fix.php?id=42423&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=42423&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=42423&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=42423&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=42423&r=mysqlcfg