Bug #17083: socket_select is closing still-needed sockets
| From: | trobinson at gksystems dot com | Date: | Tue, 07 May 2002 22:51:56 +0000 |
| Subject: | Bug #17083: socket_select is closing still-needed sockets | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-7178@lists.php.net to get a copy of this message | ||
From: trobinson@gksystems.com
Operating system: RH 7.1
PHP version: 4.2.0
PHP Bug Type: Sockets related
Bug description: socket_select is closing still-needed sockets
The script below listens on 10 ports from 26001 to 26010.
On return from socket_select, all sockets have stopped listening except
the one on which there is action, plus 26010.
This is wrong. All 10 sockets should still be listening.
strace reveals that close() is being called on the other sockets.
I suspect this is because the garbage collector does not detect
that the $listen_sockets and $r arrays are different, because for
efficiency it does not actually make a copy until one of the arrays is
modified. When the old value of $r is discarded to make way for the
results from select(),
the engine detects that the use counts on most of the socket resource
objects have gone to zero.
The two exceptions are the socket that woke up select(), and the 10th
created socket still stored in $sock.
To test this, I added $sockcopy as yet another copy of all the sockets.
The problem persisted.
Next, I added an additional junk value to $sockcopy to force the
engine to make a separate internal copy, instead of keeping just a
reference.
That fixed the problem.
...Tom Robinson
#!/usr/local/bin/php -q
<?php
ob_implicit_flush ();
for ($i = 1; $i <= 10 ; ++$i){
($sock = socket_create(AF_INET, SOCK_STREAM, 0)) or die ("socket $i");
socket_setopt($sock, SOL_SOCKET, SO_REUSEADDR, 1);
($b= socket_bind($sock, '0.0.0.0', 26000+$i)) or die("bind $i");
($l= socket_listen($sock, 4)) or die ("listen $i");
socket_set_nonblock($sock);
$listen_sockets[$i] = $sock;
}
$sockcopy = $listen_sockets; // for speed, engine makes just
a reference until one of them changes
//$sockcopy["end"] = "more stuff"; // so engine makes a copy right now
$r = $listen_sockets;
echo '
To see the 10 listening sockets: netstat -a | grep 260
Then connect to one of the ports: telnet localhost 26005
This will cause select to return. Repeat the netstat - only 2 sockets
listening now!
Then repeat the procedure, un-commenting the //$sockcopy["end"] line.
Waiting on select()...';
$x = socket_select($r, $w = null, $e = null, null);
echo "\n";
echo "select r: ", count($r), " w: ", count($w), " e: ", count($e),
"\n";
echo "Sleep 30 s before exiting..."; sleep(30); echo "\n";
exit();
?>
--
Edit bug report at http://bugs.php.net/?id=17083&edit=1
--
Fixed in CVS: http://bugs.php.net/fix.php?id=17083&r=fixedcvs
Fixed in release: http://bugs.php.net/fix.php?id=17083&r=alreadyfixed
Need backtrace: http://bugs.php.net/fix.php?id=17083&r=needtrace
Try newer version: http://bugs.php.net/fix.php?id=17083&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=17083&r=support
Expected behavior: http://bugs.php.net/fix.php?id=17083&r=notwrong
Not enough info: http://bugs.php.net/fix.php?id=17083&r=notenoughinfo
Submitted twice: http://bugs.php.net/fix.php?id=17083&r=submittedtwice
register_globals: http://bugs.php.net/fix.php?id=17083&r=globals