[php-src] Issue #23983: Function JIT (8.4+): wrong result after interrupts are handled in a loop
| From: | frodeborli | Date: | Tue, 29 Sep 2026 09:48:12 +0000 |
| Subject: | [php-src] Issue #23983: Function JIT (8.4+): wrong result after interrupts are handled in a loop | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-252849@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/23983
Author: frodeborli
### Description
With the function JIT (
opcache.jit=function) on PHP 8.4 and later, the function below
returns a wrong result when interrupts (EG(vm_interrupt)) are handled while its loops
run. Here the interrupt comes from pcntl_async_signals(); any
zend_interrupt_function user triggers it the same way.
```php
<?php
$n = 0;
pcntl_async_signals(true);
pcntl_signal(SIGUSR1, function () use (&$n) { $n++; });
$pid = getmypid();
$p = proc_open(['sh', '-c', "while kill -USR1 $pid 2>/dev/null; do sleep
0.01; done"], [], $pipes);
function f(&$n) {
$x = 7;
for ($i = 1; $n < 20; $i++) {
$x = ($x * 31 + $i) & 0xffffff;
}
$y = 7;
for ($j = 1; $j < $i; $j++) {
$y = ($y * 31 + $j) & 0xffffff;
}
return $x === $y;
}
var_dump(f($n));
proc_terminate($p);
```
```
php -d opcache.enable_cli=1 -d opcache.jit=function -d opcache.jit_buffer_size=64M test.php
```
Resulted in this output:
```
bool(false)
```
But I expected this output instead:
```
bool(true)
```
It fails on every run with 8.4.16, 8.5.11 and master; 8.2.30 and 8.3.35 (the pre-IR JIT) print
bool(true), as do 8.4+ with opcache.jit=tracing or without the JIT. Small
changes make it pass: $e = $x === $y; return $e;, returning [$x === $y, $x,
$y] (which shows $x and $y equal), or a var_dump()
inside f(). So it looks like a register-allocated value not being kept across the
interrupt handler call.
### PHP Version
```
PHP 8.5.11 (cli) (NTS), also 8.4.16 and master (8.7.0-dev)
```
### Operating System
Ubuntu 24.04, x86_64