Fix: Request State Isolation in Persistent Workers - #330
Merged
Merged
Conversation
Member
Author
|
@rrr63 @xentixar The changes cover:
I also added regression coverage for multiple dispatches using the same application/router instance. Validation completed successfully: Please pay particular attention to the lifecycle/cleanup logic and whether the behavior remains compatible with the existing lifecycle. |
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.
Fix Request State Isolation in Persistent Workers
Summary
Fixed request-state leakage across persistent workers such as Swoole, FrankenPHP worker mode, and RoadRunner.
The fixes ensure that container state, middleware, dynamically resolved services, and runtime configuration remain isolated between requests.
What Was Fixed
1. Container State Isolation
DI/Container.phphad$bindingsand$instancesdefined asprivate static, causing allContainer/Applicationinstances to share the same bindings and resolved instances.This is generally invisible under PHP-FPM/CLI because the PHP process ends after the request, but becomes problematic in persistent workers and can cause concurrent requests to overwrite request-specific services.
Fix:
$bindingsand$instancesto instance-level properties.Container::$instancestatic as the active-container pointer.2. Request-Local Middleware Pipeline
Global and group middleware were previously initialized during application boot and could therefore capture the wrong request in persistent workers.
Route middleware also mutated the shared
Gatewaymiddleware chain, causing middleware to accumulate across requests.Fix:
Router::resolve()now builds a fresh middleware chain for every request.3. Request-Scoped Dynamic Bindings
Dynamic bindings such as
FormRequestclasses and#[Bind]/#[Resolver(singleton: true)]could leave their resolved instances in the container after the request completed.This could cause request-specific objects to be reused by subsequent requests.
Fix:
Container::snapshotBootBindings().Container::forgetRequestScopedInstances().4. Runtime Configuration Isolation
Config::set()previously modified the shared configuration state and immediately rewrote the cachedconfig.phpfile.This could cause runtime changes such as
Application::setLocale()or request-levelconfig()changes to leak into subsequent requests and potentially affect other FPM workers.Fix:
Config::set()now only modifies runtime configuration.Config::resetRuntimeOverrides().5. General Request Cleanup
Generalized
Application::cleanupRequestScopedServices()so it automatically cleans up request-scoped state instead of relying on a hardcoded list of services.Result
Request-specific state is now properly isolated across requests, making the application safe for persistent worker environments while preserving the existing PHP-FPM/CLI behavior.