php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79994 pcntl_signal_get_handler() should return SIG_IGN for externally ignored signals
Submitted: 2020-08-18 21:07 UTC Modified: 2020-08-18 22:35 UTC
From: weirdan at gmail dot com Assigned:
Status: Open Package: PCNTL related
PHP Version: 7.4.9 OS: Linux (Debian/sid)
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2020-08-18 21:07 UTC] weirdan at gmail dot com
Description:
------------
Originally discovered by John Stevenson here: https://github.com/composer/xdebug-handler/issues/109#issuecomment-675462698

When signal is set to be ignored by the process that calls php binary, pcntl_signal_get_handler() run in the context of that binary reports that same signal as using default handler (SIG_DFL). However it's clearly doesn't use default handler, as can demonstrated by the script below. If it was using default handler, you'd be able to abort the script with Ctrl-C, but you can't.

PS: use Ctrl-\ to stop it.

Test script:
---------------
<?php
var_dump(
    "Is default handler is used for sigint?", 
    pcntl_signal_get_handler(SIGINT) === SIG_DFL
);

while (true) {
    echo ".";
    sleep(2);
}

// Run it as follows (in bash/zsh):
// $ trap "" SIGINT; php test.php; trap - SIGINT;

Expected result:
----------------
string(38) "Is default handler is used for sigint?"
bool(false)
..................


Actual result:
--------------
string(38) "Is default handler is used for sigint?"
bool(true)
..................


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-08-18 21:18 UTC] requinix@php.net
Not a bug, but I'll get to that.

First, a question: what should pcntl_signal_get_handler() be returning?
 [2020-08-18 21:21 UTC] weirdan at gmail dot com
It should return SIG_IGN in this case.
 [2020-08-18 21:43 UTC] requinix@php.net
-Summary: pcntl_signal_get_handler() returns SIG_DFL for externally ignored signals +Summary: pcntl_signal_get_handler() should return SIG_IGN for externally ignored signals
 [2020-08-18 21:43 UTC] requinix@php.net
Ah, you're reporting something slightly different than I thought. That's why I like asking questions. I'm slightly rewording the summary in case I'm not the only one mistaken.

Assuming that trap(1) is calling signal(7) or sigaction(7) with SIG_IGN, and given that sigaction is capable of returning the current signal handler (including whether it's ignored), then I agree that returning SIG_IGN is better than SIG_DFL.

Currently, PHP is returning what PHP was told to do. No custom handler means SIG_DFL.

I don't see that signal can return the current handler, though, so unless there's another function that can then this change in behavior may have to be platform-dependent.
 [2020-08-18 22:31 UTC] weirdan at gmail dot com
> I don't see that signal can return the current handler, though, so unless there's another function that can then this change in behavior may have to be platform-dependent.

Doesn't PHP use sigaction(), rather than signal() though? Looking at zend_sigaction() signature [1] it appears it should be possible to query the installed handler by calling zend_sigaction(SIGINT, NULL, &handler). As far as I can see, initial signal handlers are populated exactly the same way (but with actual sigaction()) into the global_orig_handlers [2] and then copied to zend_signal_globals on every request [3], from where they can be accessed by zend_sigaction() 

[1] https://github.com/php/php-src/blob/91fbd12d5736b3cc9fc6bc2545e877dd65be1f6c/Zend/zend_signal.c#L226
[2] https://github.com/php/php-src/blob/91fbd12d5736b3cc9fc6bc2545e877dd65be1f6c/Zend/zend_signal.c#L394-L404
[3] https://github.com/php/php-src/blob/91fbd12d5736b3cc9fc6bc2545e877dd65be1f6c/Zend/zend_signal.c#L376
 [2020-08-18 22:35 UTC] requinix@php.net
> Doesn't PHP use sigaction(), rather than signal() though?
I saw a "php_signal" function and didn't look too closely, but yes: php_signal -> php_signal4 -> zend_signal -> sigaction. So that's good.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Fri Oct 30 06:01:28 2020 UTC