Description
pcntl_signal() declares its third parameter as a non-nullable bool defaulting to true, but the implementation accepts null and uses a different default for SIGALRM.
The following code:
<?php
$p = (new ReflectionFunction('pcntl_signal'))->getParameters()[2];
var_dump($p->getType() . ''); // declared type
var_dump($p->allowsNull()); // declared nullability
var_dump($p->getDefaultValue()); // declared default
pcntl_signal(SIGALRM, fn() => null, null);
echo "null accepted\n";
Resulted in this output:
string(4) "bool"
bool(false)
bool(true)
null accepted
But I expected null to be rejected, since the parameter is declared non-nullable.
Two things do not match ext/pcntl/pcntl.stub.php:
1. Nullability. The stub says bool $restart_syscalls = true, so the generated arginfo marks it non-nullable, but ZPP uses Z_PARAM_BOOL_OR_NULL(). null is therefore accepted, with no deprecation.
2. Default value. The declared default is true, but for SIGALRM the effective value is false when the argument is omitted or null — ext/pcntl/pcntl.c:
/* If restart_syscalls was not explicitly specified and the signal is SIGALRM, then default
* restart_syscalls to false. PHP used to enforce that restart_syscalls is false for SIGALRM,
* so we keep this differing default to reduce the degree of BC breakage. */
if (restart_syscalls_is_null && signo == SIGALRM) {
restart_syscalls = 0;
}
So code relying on the declared default gets system call restarting disabled for SIGALRM, and Reflection gives no hint of it.
This is not a regression: the branch is present at least since 7.4.0 and is unchanged in 8.3, 8.4 and 8.5. I am reporting it because the declared signature is what tooling and the manual go by. A documentation note is at php/doc-en#5821, but the signature still describes something the implementation does not do.
?bool $restart_syscalls = null would describe the current behaviour, at the cost of a signature change.
PHP Version
PHP 8.5.4
Operating System
Linux
Description
pcntl_signal()declares its third parameter as a non-nullablebooldefaulting totrue, but the implementation acceptsnulland uses a different default forSIGALRM.The following code:
Resulted in this output:
But I expected
nullto be rejected, since the parameter is declared non-nullable.Two things do not match
ext/pcntl/pcntl.stub.php:1. Nullability. The stub says
bool $restart_syscalls = true, so the generated arginfo marks it non-nullable, but ZPP usesZ_PARAM_BOOL_OR_NULL().nullis therefore accepted, with no deprecation.2. Default value. The declared default is
true, but forSIGALRMthe effective value isfalsewhen the argument is omitted ornull—ext/pcntl/pcntl.c:So code relying on the declared default gets system call restarting disabled for
SIGALRM, and Reflection gives no hint of it.This is not a regression: the branch is present at least since 7.4.0 and is unchanged in 8.3, 8.4 and 8.5. I am reporting it because the declared signature is what tooling and the manual go by. A documentation note is at php/doc-en#5821, but the signature still describes something the implementation does not do.
?bool $restart_syscalls = nullwould describe the current behaviour, at the cost of a signature change.PHP Version
PHP 8.5.4
Operating System
Linux