Bluehost.com Web Hosting $6.95

socket_select() hangs sometimes; Bug?

This is a discussion on socket_select() hangs sometimes; Bug? within the PHP General forums, part of the PHP Programming Forums category; Hi folks, I am battling around with socket_select() for some months now and still have an unsolved problem with random ...


Go Back   Usenet Forums > PHP Programming Forums > PHP General

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 11-25-2003
Thomas Weber
 
Posts: n/a
Default socket_select() hangs sometimes; Bug?

Hi folks,

I am battling around with socket_select() for some months now and still have
an unsolved problem with random hanging.

PHP: 4.3.4 with -sockets, -sigchild, -pcntl and some other things
OS: FreeBSD 5.0 (same problem with 4.8 and 5.1)

In simple words, I have a server-daemon (runs with PHP4.3.4 now) wich uses
socket_select() for accepting new connections and dealing with existing
ones. It is an IRC-like chatserver talking with PHP-script running on a
webserver on _the same_ machine, same IP, long connects for output, short
connects for input. For debugging I use normal TCP-sockets, not
unix-domain-sockets. The select runs on all connected sockets for read and
error, write is untouched.
In testing-enviroment everything works perfect, but in production-eviroment
the server hangs after some time.

Some facts:
- in testing, even 32.000 fast connects (made synchronous with 16 processes)
couldn't get the server to hang, in production it hangs after about 3000 -
7000 connects, regardless of low CPU-load
- debug-outputs to console before and after the select show clearly the
socket_select() is hanging
- tried both blocking and non-blocking select, same effect in both cases
- both test and production are on the same machine, same PHP
- both are getting only local connects from other PHP-scripts
- socket-dumps before the select show all sockets in normal state, even if
directly before a hang
- select hangs sometimes with about 80 synchronous connections, sometimes
with only about 20

I thought it might be a bug in PHPs socket-extension, because the hangups
come random, indipendent of number of synchronous connects, number of
processed connects, id of hightest socket-descriptor, used CPU-time.
Maybe i just forgot something, but it doesn't go into my head why it hangs
exactly during the select :-/

The code should be okay, it is basically indentical to an example posted
some time ago in the php-dev-mailinglist (i've pasted it below).

#!/usr/local/bin/php -q
<?php

set_time_limit(0);


// defaults...

define('MAXLINE', 1024); // how much to read from a socket at a time
define('LISTENQ', 10); // listening queue
define('PORT', 10000); // the default port to run on
define('FD_SETSIZE', 5); // file descriptor set size (max number of
concurrent clients)...


// for kill the biatch...

function killDaemon()
{
global $listenfd, $client;

socket_close($listenfd);
$msg = "Daemon going down!\n";
for ($i = 0; $i < FD_SETSIZE; $i++)
{
if ($client[$i] != null)
{
socket_write($client[$i], $msg, strlen($msg));
socket_close($client[$i]);
}
}

print "Shutting down the daemon\n";
exit;
}


// whenever a client disconnects...

function closeClient($i)
{
global $client, $remote_host, $remote_port;

print "closing client[$i] ({$remote_host[$i]}:{$remote_port[$i]})\n";

socket_close($client[$i]);
$client[$i] = null;
unset($remote_host[$i]);
unset($remote_port[$i]);
}


// set up the file descriptors and sockets...

// $listenfd only listens for a connection, it doesn't handle anything
// but initial connections, after which the $client array takes over...

$listenfd = socket_create(AF_INET, SOCK_STREAM, 0);
if ($listenfd)
print "Listening on port " . PORT . "\n";
else
die("AIEE -- socket died!\n");

socket_setopt($listenfd, SOL_SOCKET, SO_REUSEADDR, 1);
if (!socket_bind($listenfd, "0.0.0.0", PORT))
{
socket_close($listenfd);
die("AIEE -- Couldn't bind!\n");
}
socket_listen($listenfd, LISTENQ);


// set up our clients. After listenfd receives a connection,
// the connection is handed off to a $client[]. $maxi is the
// set to the highest client being used, which is somewhat
// unnecessary, but it saves us from checking each and every client
// if only, say, the first two are being used.

$maxi = -1;
for ($i = 0; $i < FD_SETSIZE; $i++)
$client[$i] = null;


// the main loop.

while(1)
{
$rfds[0] = $listenfd;

for ($i = 0; $i < FD_SETSIZE; $i++)
{
if ($client[$i] != null)
$rfds[$i + 1] = $client[$i];
}


// block indefinitely until we receive a connection...

$nready = socket_select($rfds, $null, $null, null);


// if we have a new connection, stick it in the $client array,

if (in_array($listenfd, $rfds))
{
print "listenfd heard something, setting up new client\n";

for ($i = 0; $i < FD_SETSIZE; $i++)
{
if ($client[$i] == null)
{
$client[$i] = socket_accept($listenfd);
socket_setopt($client[$i], SOL_SOCKET, SO_REUSEADDR, 1);
socket_getpeername($client[$i], $remote_host[$i],
$remote_port[$i]);
print "Accepted {$remote_host[$i]}:{$remote_port[$i]} as
client[$i]\n";
break;
}

if ($i == FD_SETSIZE - 1)
{
trigger_error("too many clients", E_USER_ERROR);
exit;
}
}
if ($i > $maxi)
$maxi = $i;

if (--$nready <= 0)
continue;
}


// check the clients for incoming data.

for ($i = 0; $i <= $maxi; $i++)
{
if ($client[$i] == null)
continue;

if (in_array($client[$i], $rfds))
{
$n = trim(socket_read($client[$i], MAXLINE));

if (!$n)
closeClient($i);
else
{
// if a client has sent some data, do one of these:

if ($n == "/killme")
killDaemon();
else if ($n == "/quit")
closeClient($i);
else
{
// print something on the server, then echo the incoming
// data to all of the clients in the $client array.

print "From {$remote_host[$i]}:{$remote_port[$i]},
client[$i]: $n\n";
for ($j = 0; $j <= $maxi; $j++)
{
if ($client[$j] != null)
socket_write($client[$j], "From client[$i]:
$n\r\n");
}
}
}

if (--$nready <= 0)
break;
}
}
}

?>


thanks for help,

Thomas 'Neo' Weber
---
thomas@youngarts.org
neo@gothic-chat.de
Reply With Quote
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On




All times are GMT +1. The time now is 05:11 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0