php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71448 declare(ticks=1) limited to scope of file makes Signal handling difficult
Submitted: 2016-01-25 21:42 UTC Modified: 2017-03-14 13:03 UTC
Votes:16
Avg. Score:4.2 ± 0.9
Reproduced:14 of 15 (93.3%)
Same Version:7 (50.0%)
Same OS:8 (57.1%)
From: dave at atst dot io Assigned:
Status: Wont fix Package: PCNTL related
PHP Version: 7.0Git-2016-01-25 (Git) OS: Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2016-01-25 21:42 UTC] dave at atst dot io
Description:
------------
Not sure if this is intended behaviour or fallout from other declare directives intending to be scoped to a particular file.

The manual states:

The declare construct can also be used in the global scope, affecting all code following it (however if the file with declare was included then it does not affect the parent file).

I've attached a script that tries to show what I'm trying to do automatically, but you can remove the forking and just try and ctrl-c from your terminal.

Test script:
---------------
<?php

declare(ticks=1);

$start = time();
pcntl_signal(SIGINT, function() use ($start) {
    $diff = time() - $start;
    echo "SIGINT received after $diff seconds\n";
    exit;
});

$id = posix_getpid();

$child = pcntl_fork();

if ($child) {
    include 'inc.php';
} else {
    posix_kill($id, SIGINT);
}


## inc.php

<?php

$a = 0;
$start = time();
while(time() < $start + 5) {
    $a = $a + 2; # something tickable
}


Expected result:
----------------
SIGINT received after 0 seconds

Actual result:
--------------
SIGINT received after 5 seconds

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-04-25 01:19 UTC] nathan dot renniewaldock at gmail dot com
I've noticed this too.
I've got an IRC bot in PHP, I'm handling SIGINT to clean up before exiting.
With declare(ticks=1] in an included file,
in 5.6.20: triggered near instant
in 7.0.4: can take up to 20 seconds. Near instant after moving declare to the main file. There's also no mention of this change in the migration guide.
 [2016-05-14 16:26 UTC] hamid dot a85 at gmail dot com
We were trying to add a timeout feature to laravel artisan command `queue:work`. But the tests failed in PHP 7.0:
Pull request: https://github.com/laravel/framework/pull/13425

A simpler test case that fails:
https://github.com/halaei/ticks-bug-php-7
https://travis-ci.org/halaei/ticks-bug-php-7/builds/130244558

Code:
#main.php
<?php

declare(ticks=1);
pcntl_signal(SIGALRM, function ($sig) {
    die(0);
});

require_once __DIR__ . '/loop.php';


#loop.php
<?php

pcntl_alarm(2);
while (true) {
    sleep(10);
}


Expected behavior: the code terminates after 2 seconds
Observed behavior: the code will never terminate.
 [2016-05-14 17:22 UTC] nikic@php.net
-Status: Open +Status: Wont fix
 [2016-05-14 17:22 UTC] nikic@php.net
Due to an implementation bug, the declare(ticks=1) directive leaked into different compilation units prior to PHP 7.0. This is not how declare() directives, which are per-file or per-scope, are supposed to work.

Using a single declare(ticks=1) in some class inside a multi-class autoloaded project doesn't make a lot of sense. Even on PHP 5.x declare(ticks=1) would only affect code that is compiled starting from that declaration, which means that depending on the loading order of classes your whole codebase might end up using ticks or maybe only a few classes that were loaded late. (Not to mention that using ticks will make your code many times slower, but that's a different issue.)

For PHP 7.1 we may make automatic pcntl signal handling work without ticks, as we now have a new internal mechanism for handling ordinary timeouts which we can reuse.
 [2017-03-14 13:03 UTC] nikic@php.net
As an update on the previous comment: PHP 7.1 supports async signals, see https://wiki.php.net/rfc/async_signals. It looks like pcntl_async_signals() is not documented yet. This allows handling signals without using ticks.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sun Jun 16 19:01:27 2019 UTC