php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78046 pcntl_async_signals breaks down magic getter
Submitted: 2019-05-21 09:45 UTC Modified: 2019-05-22 07:50 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: toxbyte at gmail dot com Assigned:
Status: Open Package: PCNTL related
PHP Version: 7.3.5 OS: Ubuntu
Private report: No CVE-ID: None
 [2019-05-21 09:45 UTC] toxbyte at gmail dot com
Description:
------------
When use "pcntl_async_signals(true)" and try to access the magic property from async signal handler and regular way in same time, get error "Undefined property". 

PHP 7.1 7.2 7.3:
docker run -it --rm -v "$PWD":/app php:7.1.29-cli sh -c "docker-php-ext-install -j"$(getconf _NPROCESSORS_ONLN)" pcntl && php /app/test-magic.php"
docker run -it --rm -v "$PWD":/app php:7.2.18-cli sh -c "docker-php-ext-install -j"$(getconf _NPROCESSORS_ONLN)" pcntl && php /app/test-magic.php"
docker run -it --rm -v "$PWD":/app php:7.3.5-cli sh -c "docker-php-ext-install -j"$(getconf _NPROCESSORS_ONLN)" pcntl && php /app/test-magic.php"

Test script:
---------------
<?php //test-magic.php
$obj = new TestMagic;
$childrenCount = 100;
$completed = 0;

pcntl_async_signals(true);

set_error_handler(static function (int $errNo, string $errStr) {
    throw new \ErrorException("ERROR #{$errNo}: {$errStr}");
});

pcntl_signal(SIGINT, static function () {exit;});
pcntl_signal(SIGTERM, static function () {exit;});
pcntl_signal(SIGCHLD, static function () use ($obj, &$completed) {
    $completed++;
    echo "ASYNC ACCESS #{$completed} ";
    echo "{$obj->x}\n";
});

$inRun = 0;
while (++$inRun <= $childrenCount) {
    proc_open('sleep ' . (random_int(1, 999) / 1000), [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes);
}

while ($completed < $childrenCount) {
    echo "BLOCKING ACCESS #{$completed} ";
    echo "{$obj->x}\n";
}

/** @property $x */
class TestMagic
{
    public function __set($name, $value)
    {
        return null;
    }

    public function __get($name)
    {
        return 'OK';
    }

    public function __isset($name)
    {
        return true;
    }
}

// ...
// BLOCKING ACCESS #5 OK
// BLOCKING ACCESS #5 ASYNC ACCESS #6 
// Fatal error: Uncaught ErrorException: ERROR #8: Undefined property: TestMagic::$x in /app/test-magic.php:9
// Stack trace:
// #0 /app/test-magic.php(17): {closure}(8, 'Undefined prope...', '/app/test-magic...', 17, Array)
// #1 /app/test-magic.php(41): {closure}(17, Array)
// #2 /app/test-magic.php(27): TestMagic->__get('x')
// #3 {main}
//   thrown in /app/test-magic.php on line 9
// Segmentation fault (core dumped)



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-05-22 07:50 UTC] nikic@php.net
Not sure what we can do about this. This is in line with the usual semantics of accessing properties within __get, even though here it happens through a signal handler executed inside __get.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC