Skip to content

Commit 2006d70

Browse files
committed
fix: patch PHP 8.4.x opcache reset races (php/php-src#21778)
Bundles the EBR reset-safety patch from upstream PR #21778 as a source-extract hook so tarball builds pick it up automatically. The patch fixes zend_mm_heap corruption crashes triggered by opcache_reset()/opcache_invalidate() racing concurrent readers under ZTS (FrankenPHP) and FPM. - src/globals/patch/php84_opcache_ebr_reset_safety.patch: verbatim from PR #21778 commit e110a901 (NEWS hunk stripped for release tarball compatibility) - SourcePatcher::patchPhpOpcacheEbrResetSafety gated on 80400 <= ver < 80500 with an idempotency probe against accel_try_complete_deferred_reset Remove once the fix is merged and tagged into an 8.4.x release.
1 parent d26a081 commit 2006d70

File tree

2 files changed

+643
-0
lines changed

2 files changed

+643
-0
lines changed

src/SPC/store/SourcePatcher.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public static function init(): void
2121
FileSystem::addSourceExtractHook('openssl', [__CLASS__, 'patchOpenssl11Darwin']);
2222
FileSystem::addSourceExtractHook('swoole', [__CLASS__, 'patchSwoole']);
2323
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchPhpLibxml212']);
24+
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchPhpOpcacheEbrResetSafety']);
2425
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchGDWin32']);
2526
// FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchFfiCentos7FixO3strncmp']);
2627
FileSystem::addSourceExtractHook('sqlsrv', [__CLASS__, 'patchSQLSRVWin32']);
@@ -624,6 +625,38 @@ public static function patchPhpLibxml212(): bool
624625
return false;
625626
}
626627

628+
/**
629+
* Apply opcache EBR reset-safety fix (upstream PR php/php-src#21778)
630+
* to PHP 8.4.x until it lands in a tagged release. Fixes zend_mm_heap
631+
* corruption crashes caused by opcache_reset()/opcache_invalidate()
632+
* racing with concurrent readers under ZTS (FrankenPHP) and FPM.
633+
*
634+
* Fixes GH-8739, GH-14471, GH-18517.
635+
*/
636+
public static function patchPhpOpcacheEbrResetSafety(): bool
637+
{
638+
$file = SOURCE_PATH . '/php-src/main/php_version.h';
639+
if (!file_exists($file)) {
640+
return false;
641+
}
642+
if (preg_match('/PHP_VERSION_ID (\d+)/', file_get_contents($file), $match) === 0) {
643+
return false;
644+
}
645+
$ver_id = intval($match[1]);
646+
// Apply only to PHP 8.4.x releases prior to the version that ships the fix.
647+
// Upper bound will be tightened once PR #21778 is merged and tagged.
648+
if ($ver_id < 80400 || $ver_id >= 80500) {
649+
return false;
650+
}
651+
// Skip if already applied (e.g. rerunning on an already-patched tree)
652+
$probe = SOURCE_PATH . '/php-src/ext/opcache/ZendAccelerator.c';
653+
if (file_exists($probe) && str_contains(file_get_contents($probe), 'accel_try_complete_deferred_reset')) {
654+
return false;
655+
}
656+
self::patchFile('php84_opcache_ebr_reset_safety.patch', SOURCE_PATH . '/php-src');
657+
return true;
658+
}
659+
627660
public static function patchGDWin32(): bool
628661
{
629662
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');

0 commit comments

Comments
 (0)