Hi, I have a problem with socket_select()
. I hope someone here can
point me in the right direction, because I'm stumped.
Basically, I'm getting this error:
Warning: socket_select()
[function.socket-select]: no resource arrays
were passed to select in Net/Gearman/Client.php on line 197
This is using the Net_Gearman PEAR package to submit a Gearman job.
The job is submitted and runs to completion; this message is displayed
by the caller.
The relevant code is here:
http://code.google.com/p/netgearman/source/browse/trunk/Net/Gearman/Client.php#197
$write = null;
$except = null;
$read = $this->conn;
socket_select($read, $write, $except, 10);
If I add var_dump($read) on the line above socket_select()
, I get:
array(2) {
[0]=>
resource(141) of type (Socket)
[1]=>
resource(142) of type (Socket)
}
The error message appears to be spurious. This is where the socket is
created:
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
@socket_connect($socket, $host, $port);
$errorCode = socket_last_error($socket);
socket_set_nonblock($socket);
socket_set_option($socket, SOL_TCP, 1, 1);
I removed the @, and there were no errors being hidden. I resorted to
examining the socket extension code, and these are my findings:
socket_select()
calls php_sock_array_to_fd_set() on $read / $write /
$except:
http://cvs.php.net/viewvc.cgi/php-src/ext/sockets/sockets.c?revision=1.199&view=markup#l788
If the result of all three of those operations is zero, the error
message is displayed.
php_sock_array_to_fd_set() checks to see if the argument it got is an
array:
http://cvs.php.net/viewvc.cgi/php-src/ext/sockets/sockets.c?revision=1.199&view=markup#l710
If not, it returns zero.
php_sock_array_to_fd_set() calls zend_fetch_resource():
http://cvs.php.net/viewvc.cgi/php-src/ext/sockets/sockets.c?revision=1.199&view=markup#l716
If that returns zero for every element in the array,
php_sock_array_to_fd_set() also returns zero.
Since I'm dumping $read directly before the socket_select()
call, it
seems that the zend_fetch_resource() call is what's failing.
I wrote a simple testcase that submits a single job to Gearman. If I
run it under Apache2, I get the socket_select()
warning. If I run it
from the CLI, I don't. I'm also pointing the CLI at the Apache2
php.ini file. At this point, I don't know how to track this any
further. If I was getting the same error on the CLI, I could trace it
with gdb. I don't know how I'd go about doing something like that for
an Apache extension.
I'm running PHP 5.2.0 under Debian Etch, installed from the vanilla
Debian packages (5.2.0-8+etch1). I have APC and Memcache extensions
installed from PECL. I disabled both, and there was no change in what
I'm seeing. I also emailed everyone listed in socket.c, but I got no
response.
I'm at a loss. Where do I go from here?
- Ian
Ian Eure wrote:
I wrote a simple testcase that submits a single job to Gearman. If I run
it under Apache2, I get thesocket_select()
warning. If I run it from
the CLI, I don't. I'm also pointing the CLI at the Apache2 php.ini file.
At this point, I don't know how to track this any further. If I was
getting the same error on the CLI, I could trace it with gdb. I don't
know how I'd go about doing something like that for an Apache extension.
A really quick answer to this part:
If you want to trace this with gdb run Apache2, stop apache processes,
then run apache under gdb like this:
% sudo gdb apache2
run -X
You can set the breakpoint before "run -X" or after it finishes loading
by stopping it with Ctrl-C, setting breakpoint, and cont'inuing. -X
ensures that it runs only a single process.
-Andrei