Message-ID: <4F391357.4060102@zend.com>
Date: Mon, 13 Feb 2012 17:42:47 +0400
From: Dmitry Stogov <dmitry@zend.com>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20120131 Thunderbird/10.0
To: Lucas Nealan <lucas@php.net>, Arnaud Le Blanc <lbarnaud@php.net>
CC: Yoram bar-haim <bhyoram@zahav.net.il>, <alex.h@zend.com>,
	<smalyshev@sugarcrm.com>, Rasmus Lerdorf <rasmus@php.net>, Andi Gutmans
	<andi@zend.com>, Zeev Suraski <Zeev@zend.com>
Subject: Re: signals hadling problem in PHP 5.4
References: <201202081858.12387.bhyoram@zahav.net.il>
In-Reply-To: <201202081858.12387.bhyoram@zahav.net.il>
Content-Type: text/plain; charset="ISO-8859-1"; format=flowed
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0

Hi Arnaud and Lucas,

I can confirm the problem. Just start Apache with mod_php, generate some 
load (e.g. ab -t 120 http://.../hello.php), then run 'apachectl restart' 
for few times, then 'apachectl stop'. You will see warning and error 
messages in error_log

[warn] child process 15317 still did not exit, sending a SIGTERM

[error] child process 15317 still did not exit, sending a SIGKILL

The problem goes away if I compile php without ZEND_SIGNALS.

I tried to analyze and debug zend_signal.c and found very wired behavior.

On first request zend_signal_activate() sets its own signal handler for 
SIGHUP and stores the original handler in 
SIGG(handlers)[SIGHUP-1].handler, but on second request the same 
zend_signal_activate() overwrites the original signal handler by handler 
from parent process.

zend_signal.c:284

memcpy(&SIGG(handlers), &global_orig_handlers, 
sizeof(global_orig_handlers));

As result the original signal handler for SIGHUP is never called.
Even worse after restart and two request 
SIGG(handlers)[SIGHUP-1].handler becomes SIG_IGN and SIGHUP is ignored 
at all.

I'm not going to fix it myself.

Thanks. Dmitry.

On 02/08/2012 08:58 PM, Yoram bar-haim wrote:
> Hello all.
> After intensive debugging of PHP restart issues (child processes don't go down
> fast enough for apache, so SIGTERM and sometimes SIGKILL are sent), I found
> out the following problem in PHP signal handling mechanism.
>
> on startup (zend_signal_startup()), :
> 	PHP copies the current sigactions for all signals into
> global_orig_handlers.
> on activate (zend_signal_activate()) :
> 	global_orig_handlers are copied int zend_global_handlers.
> 	zend_signal_handler_defer is registered as signal handler (also in
> zend_global_handlers).
>
> Please note that zend_signal_startup() happens *before* set_signals() in
> apache startup.
>
> his logic works fine, unless SIGHUP is called after zend_signal_activate() was
> started but before zend_signal_register() finished to register handler.
> on that situation, the default (SIG_IGN) will found in
> zend_global_handlers.handlers[0].handler by zend_signal_handler and the signal
> will be ignored.
> as result, child shutdown will not occur on SIGHUP but only later on SIGTERM.
>
> I'm still trying to find a fix for this problem, but it will be better if Dmitry
> ans Stas  will also take a look.
>
