From 1df20e45d56da29a4b1d8259dd6e950acbf1b13f Mon Sep 17 00:00:00 2001 From: MatTheCat Date: Thu, 16 Mar 2023 16:48:23 +0100 Subject: [PATCH] Stop stopwatch events in case of exception --- Debug/WrappedListener.php | 10 ++++++---- Tests/Debug/WrappedListenerTest.php | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Debug/WrappedListener.php b/Debug/WrappedListener.php index 86d3854..3c4cc13 100644 --- a/Debug/WrappedListener.php +++ b/Debug/WrappedListener.php @@ -114,10 +114,12 @@ public function __invoke(object $event, string $eventName, EventDispatcherInterf $e = $this->stopwatch->start($this->name, 'event_listener'); - ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); - - if ($e->isStarted()) { - $e->stop(); + try { + ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); + } finally { + if ($e->isStarted()) { + $e->stop(); + } } if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { diff --git a/Tests/Debug/WrappedListenerTest.php b/Tests/Debug/WrappedListenerTest.php index 68db87d..115657e 100644 --- a/Tests/Debug/WrappedListenerTest.php +++ b/Tests/Debug/WrappedListenerTest.php @@ -15,6 +15,7 @@ use Symfony\Component\EventDispatcher\Debug\WrappedListener; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; class WrappedListenerTest extends TestCase { @@ -42,6 +43,25 @@ public static function provideListenersToDescribe() [\Closure::fromCallable(function () {}), 'closure'], ]; } + + public function testStopwatchEventIsStoppedWhenListenerThrows() + { + $stopwatchEvent = $this->createMock(StopwatchEvent::class); + $stopwatchEvent->expects(self::once())->method('isStarted')->willReturn(true); + $stopwatchEvent->expects(self::once())->method('stop'); + + $stopwatch = $this->createStub(Stopwatch::class); + $stopwatch->method('start')->willReturn($stopwatchEvent); + + $dispatcher = $this->createStub(EventDispatcherInterface::class); + + $wrappedListener = new WrappedListener(function () { throw new \Exception(); }, null, $stopwatch, $dispatcher); + + try { + $wrappedListener(new \stdClass(), 'foo', $dispatcher); + } catch (\Exception $ex) { + } + } } class FooListener