[php-src] Issue #24185: PHP 8.5+ Windows ZTS: random access violations with OPcache JIT in multi-process setups
| From: | alvin0319 | Date: | Thu, 08 Oct 2026 01:58:03 +0000 |
| Subject: | [php-src] Issue #24185: PHP 8.5+ Windows ZTS: random access violations with OPcache JIT in multi-process setups | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-252938@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/24185
Author: alvin0319
### Description
Reproduce code:
child.ini (same directory):
```ini
opcache.enable=1
opcache.enable_cli=1
opcache.protect_memory=1
opcache.jit=1205
opcache.jit_buffer_size=128M
```
repro-parent.php (parent should also use child.ini):
```php
<?php
declare(strict_types=1);
$suppress = ($argv[1] ?? 'false') === 'true';
$runs = (int) ($argv[2] ?? 10);
const ACCESS_VIOLATION = -1073741819;
$crashes = 0;
for($i = 1; $i <= $runs; $i++){
$cmd = 'start "" /b /wait ' . PHP_BINARY . ' -n -c ' . __DIR__ .
'\child.ini ' . __DIR__ . '\repro-child.php & exit';
$proc = proc_open($cmd, [0 => ['pipe', 'r'], 1 => ['pipe',
'w'], 2 => ['pipe', 'w']], $pipes, __DIR__, getenv(),
['suppress_errors' => $suppress]);
fclose($pipes[0]);
$out = stream_get_contents($pipes[1]);
fclose($pipes[1]);
fclose($pipes[2]);
$code = proc_close($proc);
if($code === ACCESS_VIOLATION){
$crashes++;
}
echo "run $i: exit $code, output: " . trim($out) . "\n";
}
echo "suppress_errors=" . var_export($suppress, true) . ": $crashes / $runs runs
crashed\n";
exit($crashes > 0 ? 1 : 0);
```
repro-child.php (must use child.ini):
```php
<?php
declare(strict_types=1);
function fixedArrayRead(SplFixedArray $array, int $index) : mixed{
return $array->offsetGet($index);
}
function makeDate(string $value) : DateTimeImmutable{
return new DateTimeImmutable($value);
}
function iteratorSeek(ArrayIterator $iterator, int $position) : void{
$iterator->seek($position);
}
$caught = 0;
$array = new SplFixedArray(1);
$iterator = new ArrayIterator([1]);
for($i = 0; $i < 10; $i++){
try{
fixedArrayRead($array, 5);
}catch(RuntimeException $e){
$caught++;
}
try{
makeDate('not a date');
}catch(Exception $e){
$caught++;
}
try{
iteratorSeek($iterator, 5);
}catch(OutOfBoundsException $e){
$caught++;
}
}
echo "caught $caught\n";
```
Run:
```
php -n -c child.ini repro-parent.php true 50
```
In theory, the child script's expected output should be caught 30 because
exceptions should be caught by try-catch. But in PHP 8.5+ (ZTS, OPcache JIT enabled),
this causes ACCESS_VIOLATION for some reason with OPcache JIT enabled.
Tests with GitHub actions runner: [action
log](https://github.com/alvin0319/php-jit-bug-testing/actions/runs/37713764335)
Full code snippets can be found on [this repo](https://github.com/alvin0319/php-jit-bug-testing)
### PHP Version
```plain
PHP 8.5.11 (cli) (built: Sep 22 2026 13:50:46) (ZTS Visual C++ 2022 x64)
Copyright (c) The PHP Group
Built by The PHP Group
Zend Engine v4.5.11, Copyright (c) Zend Technologies
with Zend OPcache v8.5.11, Copyright (c), by Zend Technologies
PHP 8.6.0RC3 (cli) (built: Oct 6 2026 17:20:27) (ZTS Visual C++ 2026 x64)
Copyright © The PHP Group and Contributors
Built by The PHP Group
Zend Engine v4.6.0RC3, Copyright © Zend by Perforce
with Zend OPcache v8.6.0RC3, Copyright ©, by Zend by Perforce
```
### Operating System
Windows 10 Pro 22H2 (10.0.19045), Windows Server 2025 (windows-2025-vs2026 runner image)