Edit report at http://bugs.php.net/bug.php?id=20745&edit=1
ID: 20745
Comment by: contact at aldrik dot net
Reported by: polone at townnews dot com
Summary: socket_accept() in blocking mode doesn't handle
signal interrupts
Status: Closed
Type: Bug
Package: Sockets related
Operating System: Linux
PHP Version: 4.2.3
Block user comment: N
Private report: N
New Comment:
Could this bug be reopened ? Mapping of posix API isn't well done, the
workaround introduce latency and make people loose their time.
Signal are made to interrupt workflow, even on blocking situation.
Previous Comments:
------------------------------------------------------------------------
[2008-03-06 15:25:36] polone at townnews dot com
This IS a bug - all you've stated is _another_ workaround - less elegant
than just setting the socket_accept() call to non-blocking and sleeping
for 1 second (or you can sleep for microseconds in PHP 5) in the loop.
It doesn't fix the underlying problem - which is that socket_accept()
does not behave like accept().
If I issue SIGUSR1 - I should not have to set SIGALRM to 'reap' signals.
Signals are suppose to interrupt blocking waits like this. I shoudn't
have to make the accept() call non-blocking.
At the very least - the non-standard behavior of this function (and it's
caveats) should be documented.
------------------------------------------------------------------------
[2008-03-06 14:47:48] rose dot andrew at gmail dot com
This is not a bug. socket_accept() will ignore all signals expect an
alarm. I have documented how to use this method of interrupting
socket_accept() here:
http://andrew-rose.blogspot.com/2008/02/php-getting-signals-through-to-blocking.html
------------------------------------------------------------------------
[2007-11-29 01:51:59] steven dot gilberd at gmail dot com
This bug still appears to exist (PHP 5.2.3-1+b1 (cli)), on at least
socket_accept().
The signals just queue up until the socket receives a connection and
unblocks, at which point the signals are processed as normal.
I would like to request that this bug be reactivated; leaving it sitting
here as 'No Feedback' isn't helping anyone.
------------------------------------------------------------------------
[2007-03-12 18:54:30] antoine dot bajolet at tdf dot fr
Hello,
The issue still exists,
PHP Version => 4.4.6
System => Linux pentium2.antoine 2.6.20 #5 Sun Feb 18 16:28:17 CET 2007
i686
Build Date => Mar 6 2007 21:15:38
Complete code to reproduce error :
script.php
------------------------------------------------------------------
#!/usr/local/bin/php
<?php
define ( 'BIND_PORT', 3333 );
/* Signal Handler */
function signalHandler( $sig ) {
switch ( $sig ) {
case SIGTERM :
exit( 0 );
break;
case SIGCHLD :
pcntl_waitpid(-1,$status,WNOHANG);
break;
}
}
print "My PID is ".posix_getpid()."\n";
declare ( ticks = 1 );
pcntl_signal( SIGTERM, 'signalHandler' );
pcntl_signal( SIGCHLD, 'signalHandler' );
// infinite execution time
set_time_limit( 0 );
// Socket creation
$sock = socket_create ( AF_INET, SOCK_STREAM, SOL_TCP );
// Bind sur le port BIND_PORT
if ( !socket_bind( $sock, '0.0.0.0', BIND_PORT ) ) {
print "Unable to bind to port " . BIND_PORT . " !\n";
exit( 1 );
}
// Listening up to 16 buffets
socket_listen ( $sock, 16 );
// Infinite loop
while ( true ) {
// Wait for incoming connections, hangs signal handling
$subsock = socket_accept ( $sock );
// Connection received, forking sub-process
$subPid = pcntl_fork();
if ( $subPid === 0 ) {
// Get remote informations
socket_getpeername( $subsock , $remoteAddr , $remotePort );
socket_write( $subsock, 'Simple Socket Server accepting commands
from ' . $remoteAddr . "\n" );
// Whe are in interactive mode
while ( true ) {
$received = socket_read ( $subsock, 65536, PHP_NORMAL_READ
);
// Clean shutdown
if ( !$received ) {
socket_shutdown( $subsock, 2 );
socket_close( $subsock );
exit( 0 );
}
// Cleaning entry
$received = trim( $received );
if ( $received ) {
// two commands : HELLO and QUIT
switch ( $received ) {
case 'HELLO':
socket_write( $subsock, 'HELLO ' . $remoteAddr .
"\n" );
break;
case 'QUIT':
// (shutdown)
socket_write( $subsock, 'BYE' . "\n" );
socket_shutdown( $subsock, 2 );
socket_close( $subsock );
exit( 0 );
break;
default :
socket_write( $subsock, 'Unknown command...' .
"\n" );
}
}
}
}
} // while
?>
------------------------------------------------------------------
Commands :
[Shell1]$ ./script.php
My PID is 18135
[Shell2]$ kill 18135
<Happens nothing on Shell1...>
[Shell2]$ telnet localhost 3333
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host
[Shell1] : The script exits.
=> The signal is properly intercepted but the handler is only called
when the script continues after socket_accept().
Whe are using a little more complex code when the fist process is a
child of a fork itself : At this time, the only way to end it is a not
very clean SIGKILL.
Regards,
AB
------------------------------------------------------------------------
[2006-05-25 19:31:39] lindsay at bitleap dot com
I still see this issue with php 5.1.4. I did notice that the signal
will queue up and on the next inbound connection the queued signal
executes.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/bug.php?id=20745
--
Edit this bug report at http://bugs.php.net/bug.php?id=20745&edit=1