Skip to content

[EventDispatcher] Fix eventListener wrapper loop in TraceableEventDispatcher #29376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 1, 2018

Conversation

jderusse
Copy link
Member

Q A
Branch? 3.4
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets none
License MIT
Doc PR na

The TracableEventDispatcher wrap decorate (in the method preProcess) each listeners in a WrappedListener before delegating the dispatch to the real dispatcher, then remove the wrapper (in the method postProcess.

But, if a listener triggers an exception, the postProcess method is not called, and the wrapper in not removed.
If the same event is triggered a second time, the listeners will be decorated twice, etc, etc..
This is an issue with php-pm where the same event is triggered hundred of times within the same process.

This PR moves the postProcess in a finally block in order to be called even if an exception in thrown.

@ro0NL
Copy link
Contributor

ro0NL commented Nov 30, 2018

👍 included this also in #29312

@nicolas-grekas nicolas-grekas added this to the 3.4 milestone Nov 30, 2018
@chalasr chalasr changed the title [EventDispatcher] Fix eventListener wrapper loop in TracableEventDispatcher [EventDispatcher] Fix eventListener wrapper loop in TraceableEventDispatcher Nov 30, 2018
}
}
} finally {
$this->postDispatch($eventName, $event);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in #29312 i actually hesitated if we should call postDispatch after exception. That's a new behavior, where the user cant act upon as it doesnt know about an errored dispatch call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, looking at

protected function postDispatch($eventName, Event $event)
{
switch ($eventName) {
case KernelEvents::CONTROLLER_ARGUMENTS:
$this->stopwatch->start('controller', 'section');
break;
case KernelEvents::RESPONSE:
$token = $event->getResponse()->headers->get('X-Debug-Token');
$this->stopwatch->stopSection($token);
break;
case KernelEvents::TERMINATE:
// In the special case described in the `preDispatch` method above, the `$token` section
// does not exist, then closing it throws an exception which must be caught.
$token = $event->getResponse()->headers->get('X-Debug-Token');
try {
$this->stopwatch->stopSection($token);
} catch (\LogicException $e) {
}
break;
}
}
it should be OK and expected.

@nicolas-grekas
Copy link
Member

Thank you @jderusse.

@nicolas-grekas nicolas-grekas merged commit 3830a9e into symfony:3.4 Dec 1, 2018
nicolas-grekas added a commit that referenced this pull request Dec 1, 2018
…bleEventDispatcher (jderusse)

This PR was merged into the 3.4 branch.

Discussion
----------

[EventDispatcher] Fix eventListener wrapper loop in TraceableEventDispatcher

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | none
| License       | MIT
| Doc PR        | na

The `TracableEventDispatcher` wrap decorate (in the method `preProcess`) each listeners in a `WrappedListener` before delegating the dispatch to the real dispatcher, then remove the wrapper (in the method `postProcess`.

But, if a listener triggers an exception, the `postProcess` method is not called, and the wrapper in not removed.
If the same event is triggered a second time, the listeners will be decorated twice, etc, etc..
This is an issue with php-pm where the same event is triggered hundred of times within the same process.

This PR moves the `postProcess` in a finally block in order to be called even if an exception in thrown.

Commits
-------

3830a9e Fix wrapped loop of event listener
@jderusse jderusse deleted the fix-wrap-loop branch August 2, 2019 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants