10000 store $this->id in local $id to avoid errors when this value is changed by pjordaan · Pull Request #9748 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

store $this->id in local $id to avoid errors when this value is changed #9748

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

Closed
wants to merge 1 commit into from
Closed

store $this->id in local $id to avoid errors when this value is changed #9748

wants to merge 1 commit into from

Conversation

pjordaan
Copy link
Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #9727
License MIT

…ed during execution of preDispatch and postDispatch method
@fabpot
Copy link
Member
fabpot commented Dec 12, 2013

closing in favor of #9737

@fabpot fabpot closed this Dec 12, 2013
@stof
Copy link
Member
stof commented Dec 14, 2013

@fabpot This should still be considered. It is about preserving the id in different methods during which the id may change than dispatch.

However, I would like to see a testcase reproducing a case where the id is modified during these methods to demonstrate the fix

@fabpot fabpot reopened this Dec 14, 2013
@fabpot
Copy link
Member
fabpot commented Dec 29, 2013

@pjordaan Can you fork the Symfony Standard Edition to show some code that shows the issue fixed here?

@pjordaan
Copy link
Author

I'll see if I can make a working case, but I'll probably post if somewhere in the new year. The code I'm currently working on is proprietary.

The test case written in pull request #9750 is applicable.

In my case the code I have a service which does something like this:

class MyService
{
  public function __construct(EventDispatcherInterface $dispatcher) {
    $this->dispatcher = $dispatcher;
    $this->update() 
  }
  public function update() {
    //some code
    $this->dispatcher->dispatch("<event>");
  }
}

@remialvado
Copy link

A probably better way to fix it is to ensure that the wrappedListener item exists before using it. I've replaced :

foreach ($listeners as $listener) {
    $this->dispatcher->removeListener($eventName, $listener);
    $wrapped = $this->wrapListener($eventName, $listener);
    $this->wrappedListeners[$this->id][$wrapped] = $listener;
    $this->dispatcher->addListener($eventName, $wrapped);
}

by

foreach ($listeners as $listener) {
    $this->dispatcher->removeListener($eventName, $listener);
    $wrapped = $this->wrapListener($eventName, $listener);
    if (!array_key_exists($this->id, $this->wrappedListeners)) {
        $this->wrappedListeners[$this->id] = new \SplObjectStorage();
    }
    $this->wrappedListeners[$this->id][$wrapped] = $listener;
    $this->dispatcher->addListener($eventName, $wrapped);
}

and it works like a charm. But I'm not able to reproduce my previous bug in an unit test. i still don't understand why the unit test described in #9750 works and do not throw this kind of warning. Maybe the PHP warning is just ignored by PHPUnit.

@pjordaan
Copy link
Author

ok, seems I still have cases in dev where this warning is still being produced, but it doesn't happen all the time, which is really annoying.

I could fine one case where it goes wrong and see if I can write a unit test for it.

some class dispatches event1
event1listener dispatches event2
event2listener throws exception
event1listener caught exception
$this->id is no longer valid.

8000
@sp-ludovic-ivain
Copy link

+1 to @remialvado solution, i had the same problem with the TraceableEventDispatcher (#9727), and with that piece of code it works perfectly now.

@ianmonge
Copy link

I think that I can reproduce the error. The steps are:

  • Someone dispatches the event1.
  • The dispatcher store the $eventId number and calls the method preDispatch.
  • The method preDispatch tries to return all the listeners of event event1, getting them from Container.
  • One of the listeners has Dispatcher as dependency, and Container injects it to the listener.
  • The listener, in the method __construct receives the Dispatcher and dispatches an another event event2.
  • The execution starts another time the method dispatch, incrementing other time the $eventIdnumber.
  • When event2 is over, the listener can finish its construction, and Container can return the listener of the event event1.
  • Then it's when the $eventId it's not the same and appears the error Illegal offset type.

I hope you can understand the steps ☺️ I've done a test that it's not the better way to test it, but it can explain the error better than me:
https://github.com/ianmonge/symfony/compare/symfony:v2.4.1...fixTraceableEventDispatcher?expand=1

It has the fix of @remialvado.

fabpot added a commit that referenced this pull request Feb 4, 2014
…cher (fabpot)

This PR was merged into the 2.3 branch.

Discussion
----------

[HttpKernel] fixed wrong reference in TraceableEventDispatcher

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9748, #9727
| License       | MIT
| Doc PR        | n/a

This PR fixes #9748 and #9727 by removing the `id` state. Only private method signatures have been changed, so that qualifies for a fix in 2.3.

The `getNotCalledListeners()` is a bit special as it tries to get non-called listeners. It passes `null` as the event id as if a listener has been called more than once, getting the first call is enough.

Commits
-------

acd3317 [HttpKernel] fixed wrong reference in TraceableEventDispatcher
@fabpot
Copy link
Member
fabpot commented Feb 4, 2014

closing in favor of #10191

@fabpot fabpot closed this Feb 4, 2014
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.

6 participants
0