Edit report at https://bugs.php.net/bug.php?id=20745&edit=1
ID: 20745
Comment by: alien at rmail dot be
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:
if socket_accept is blocking, but still handles SIGALRM, it can perfectly handle SIGCHLD.
basically, to workaround this, all child processes would need to send an ALRM when they are exiting,
and the killing of the main process would also need to send an ALRM after the TERM signal.
Please fix this long-standing bug please, this will make php-daemons much more resource-efficient.
Previous Comments:
------------------------------------------------------------------------
[2010-12-14 17:33:42] contact at aldrik dot net
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.
------------------------------------------------------------------------
[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
------------------------------------------------------------------------
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
https://bugs.php.net/bug.php?id=20745
--
Edit this bug report at https://bugs.php.net/bug.php?id=20745&edit=1