diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php index 347c7d07399a9..b796a8125ab4d 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -224,6 +224,9 @@ private function postProcess($eventName) { $skipped = false; foreach ($this->dispatcher->getListeners($eventName) as $listener) { + if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch. + continue; + } // Unwrap listener $this->dispatcher->removeListener($eventName, $listener); $this->dispatcher->addListener($eventName, $listener->getWrappedListener()); diff --git a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php index 399f1a788980b..c2cafc37b8cfa 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php @@ -75,6 +75,24 @@ public function testStopwatchStopControllerOnRequestEvent() $kernel->handle($request); } + public function testAddListenerNested() + { + $called1 = false; + $called2 = false; + $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $dispatcher->addListener('my-event', function () use ($dispatcher, &$called1, &$called2) { + $called1 = true; + $dispatcher->addListener('my-event', function () use (&$called2) { + $called2 = true; + }); + }); + $dispatcher->dispatch('my-event'); + $this->assertTrue($called1); + $this->assertFalse($called2); + $dispatcher->dispatch('my-event'); + $this->assertTrue($called2); + } + protected function getHttpKernel($dispatcher, $controller) { $resolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');