Give spawned workers their PHP configuration on the command line - #6328
Open
ondrejmirtes wants to merge 2 commits into
Open
Give spawned workers their PHP configuration on the command line#6328ondrejmirtes wants to merge 2 commits into
ondrejmirtes wants to merge 2 commits into
Conversation
| persist-credentials: false | ||
|
|
||
| - name: "Install PHP" | ||
| uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2 |
ProcessHelper now passes spawned workers the OPcache entries of the TurboProcessRestarter restart, the restart marker, and the extension path marker next to the extension itself. Until now a spawned worker ran bin/phpstan's restart prologue unmarked: on a pcntl host it re-executed itself once to activate OPcache - rebuilding its command line without the sys_temp_dir and extension entries of the spawn - and on Windows, where no restart is possible, it ran without OPcache and so without the turbo trusted-types pass, which lives in the optimizer. Windows OPcache is a named file mapping shared by every process of the same user, build and SAPI, so identically configured workers would all attach to one segment - the concurrently populated shared cache forked workers were taken off in b293f3c, and a reattach that fails is a fatal startup error. Each Windows worker gets its own opcache.cache_id instead: a private segment, the model spawned workers have elsewhere. Workers now report in their hello whether turbo, OPcache and trusted types took effect; ParallelAnalyser prints it per spawned worker at -vvv, and diagnose lists the worker -d entries under the spawn mechanism. The phar-run job asserts on the report for every PHP version, and the new phar-run-windows job runs the phar on Windows with and without the turbo DLL next to it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdGL6QPGhAzYmN2zU4gwhH
ondrejmirtes
force-pushed
the
spawned-worker-opcache
branch
from
September 1, 2026 14:51
14ff3d2 to
e1eb1e5
Compare
…ts empty script AutoloadSourceLocator locates a class not yet loaded by running the autoloaders under FileReadTrapStreamWrapper, which records the file an autoloader includes and serves an empty script in its place. With OPcache active that empty script is compiled and cached under the path the include was given; the locator invalidates the trapped files afterwards, but on PHP < 8.1 opcache_invalidate() fails for the path of any stream wrapper other than file:// - zend_accel_invalidate() resolves the path first and php_resolve_path() refuses such URLs (8.1 falls back to the name as given). The poisoned entry then answers every later real include of the same path, the class is never declared, and its first cold use dies with "Class not found". PHPStan's own classes that preload.php leaves to the autoloader (the turbo-shadowed ones, TrinaryLogic among them) are exactly such files when running from the phar - autoloaded as phar://.../vendor/composer/../../src/TrinaryLogic.php by the phar's Composer classmap - and analysing code that references them triggers the trap. Spawned workers on PHP 7.4 and 8.0 started running with OPcache in the previous commit, which is how the extension test suites hit it. Where the invalidation cannot work, the trap now serves a parse error instead: it compiles to nothing, so OPcache stores nothing, and the locator catches the ParseError - the file was recorded before the include compiled it. Everywhere else the empty script stays, so autoloaders that require several files in a row keep being captured in full. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdGL6QPGhAzYmN2zU4gwhH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to the OPcache restart series (#6327 and the commits before it).
bin/phpstanruns the restart prologue in every process, spawned workers included, and they never received thephpstan.restartedmarker:-d sys_temp_dirand-d extension=(verified by parking a worker and reading its argv);Commit 1:
ProcessHelpernow passes spawned workers the restart's OPcache entries plus both markers (phpstan.restarted,phpstan.turboExtensionPath). On Windows every worker additionally gets its ownopcache.cache_id: OPcache there is a named file mapping shared by every process of the same user, build and SAPI (ext/opcache/shared_alloc_win32.c), so identically configured workers would all attach to one segment — the concurrently populated shared cache b293f3c took forked workers off, and a reattach that fails isexit(-2)unless a file cache is configured (we blank it). A per-worker id gives each a private segment, the model spawned workers already have on POSIX.Verification hooks: workers report in their hello whether turbo, OPcache and trusted types took effect;
-vvvprints one line per spawned worker (Spawned worker 1/2 checked in: turbo on, OPcache on, trusted types on), anddiagnoselists the worker-dentries under the spawn mechanism. Thephar-runjob now asserts on that report for every PHP version, and the newphar-run-windowsjob runs the phar on Windows on 8.2 (OPcache entries alone, no binary below 8.3) and 8.5 (with the turbo DLL placed next to the phar).Commit 2 fixes what the first one exposed in the extension test suites on PHP 7.4/8.0 (
Internal error: Class 'PHPStan\TrinaryLogic' not found):AutoloadSourceLocator's trap serves an empty script for the file an autoloader includes, OPcache caches it under the raw include path, and theopcache_invalidate()that is meant to undo that fails on PHP < 8.1 for any non-file://path (php_resolve_path()refuses such URLs; 8.1 falls back to the given name). PHPStan's own classes thatpreload.phpleaves to the autoloader — the turbo-shadowed ones — are autoloaded from the phar asphar://…/vendor/composer/../../src/…, so the first cold use after the trap died. Where the invalidation cannot work, the trap now serves a parse error instead (compiles to nothing, so nothing is cached) and the locator catches it. Reproduced and verified locally on PHP 7.4 with the CI phar (phpstan-nette, spawned worker:OPcache on→[OK] No errors).🤖 Generated with Claude Code
https://claude.ai/code/session_01VdGL6QPGhAzYmN2zU4gwhH