Skip to content

Running container is being deleted when dependency is autowired implicitly in Symfony 3 #27053

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
ostrolucky opened this issue Apr 25, 2018 · 8 comments

Comments

@ostrolucky
Copy link
Contributor

ostrolucky commented Apr 25, 2018

Q A
Bug report? yes
Feature request? no
BC Break report? no
RFC? no
Symfony version 3.4

I have changed constructor dependency from Doctrine's ApplicationRepository (which has service ID same as FCQN) into dependency which has ID not matching FCQN, configured with legacy style, like:

panel.application.application_history:
  class: AppBundle\Panel\Panels\Application\ApplicationHistory
  arguments: [ '@manager.application', '@manager.user' ]
class HistoryWindowController extends Controller
{
    private $applicationHistoryPanel;

    public function __construct(ApplicationHistory $applicationHistoryPanel)
    {
        $this->applicationHistoryPanel = $applicationHistoryPanel;
    }

    public function __invoke(Application $application)
    {
        ...
    }
}

It works. BUT

After doing that, tests started to blow up with messages like:

Symfony\Component\Debug\Exception\FatalErrorException:
Compile Error: ContainerX6wnwgd\appTestDebugProjectContainer::load(): Failed opening required '/var/www/var/cache/test/ContainerX6wnwgd/getJmsJobQueue_Entity_ManyToAnyListenerService.php' (include_path='.:/usr/local/lib/php')

  at var/cache/test/ContainerX6wnwgd/appTestDebugProjectContainer.php:2481
  at ContainerX6wnwgd\appTestDebugProjectContainer->load('file' => '???', 'lazyLoad' => '???')
     (vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:304)
  at ContainerX6wnwgd\appTestDebugProjectContainer->get('id' => '???', 'invalidBehavior' => '???')
     (vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php:58)
  at Symfony\Bridge\Doctrine\ContainerAwareEventManager->dispatchEvent('eventName' => '???', 'eventArgs' => '???')
     (vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php:117)
  at Doctrine\ORM\Event\ListenersInvoker->invoke('metadata' => '???', 'eventName' => '???', 'entity' => '???', 'event' => '???', 'invoke' => '???')
     (vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php:99)

Test looks like this:

$client = static::createClient();

$oppManager = $container->get('manager.opportunity');

$this->assertSomething($client->request(...));
$this->assertSomething($client->request(...));
$this->assertSomething($client->request(...));

$oppManager->findOneBy([])->getId(); // here it blows up

What I found is that after each $client->request(), container is being replaced, so when it comes to executing $oppManager->findOneBy(), old container folder does no longer exist, so classes which weren't loaded yet at that point, cannot.

I also tried to find out why is container being regenerated and what I found is that resource is marked as ClassExistenceResource for EntityManager5ae0c6b8bc55b_546a8d27f194334ee012bfe64f629947b07e4919\__CG__\Doctrine\ORM\EntityManager. Such key has false value in \Symfony\Component\Config\Resource\ClassExistenceResource#existsCache[1]. Variable $exists is true and $this->exists is false. This results in false return.

This issue has been discovered in Symfony 3.4.4. I updated and is still present in Symfony 3.4.8.

Issue is resolved when I alias the service so FCQN matches ID:

AppBundle\Panel\Panels\Application\ApplicationHistory: '@panel.application.application_history'

Here are some other things which might help:

  • Controller is in AppBundle, but test is in ApiBundle (and doesn't test that controller).
  • AppBundle tests don't have this issue, only ApiBundle ones

I realize these autowiring fallbacks are deprecated, but it shouldn't blow up like this and will make it hard to migrate

@ostrolucky ostrolucky changed the title Used container is being deleted when dependency is autowired implicitly in Symfony 3 Running container is being deleted when dependency is autowired implicitly in Symfony 3 Apr 25, 2018
@nicolas-grekas
Copy link
Member

Could you provide a repo with a reproducer?

@ostrolucky
Copy link
Contributor Author

ostrolucky commented Apr 26, 2018

This one is very close. Run phpunit

demo.zip

@stof
Copy link
Member

stof commented Apr 26, 2018

I think the EntityManager5ae0c6b8bc55b_546a8d27f194334ee012bfe64f629947b07e4919\__CG__\Doctrine\ORM\EntityManager class is coming from JMSDIExtraBundle. I know this bundle is causing issues with recent versions of Symfony, as it has not been updated to play well with newer versions (and some assumptions it was making are not playing well with assumptions done by Symfony DI).

@nicolas-grekas
Copy link
Member

@stof is right. Yet in this specific case, we can do something about it. See #27061.

nicolas-grekas added a commit that referenced this issue Apr 26, 2018
…loaded (nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

[HttpKernel] Don't clean legacy containers that are still loaded

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

Commits
-------

be8dbc3 [HttpKernel] Don't clean legacy containers that are still loaded
@ostrolucky
Copy link
Contributor Author

This fixed the fatal error, great job 👍

However, it doesn't fix the issue of container being unnecessarily re-generated after each request. Should I create separate issue for that?

@nicolas-grekas
Copy link
Member

Can you debug it a bit? Is this something Symfony can do about, or the bundle should do? Depending on the answer you can open an issue yes.

@ostrolucky
Copy link
Contributor Author

ostrolucky commented Apr 27, 2018

Will try, but I doubt I can debug it in reasonable time. Internals are pretty unreadable to me. Lot of nesting, inlining and no comments. I would need some help with debugging that. Is there some material explaining internals of DI?

@stof
Copy link
Member

stof commented Jun 5, 2018

The container being regenerated all the time is related to JMSDIExtraBundle replacing the EntityManager service with its own service, but defining the service class only later. As the autowiring considers non-existent classes differently than existing classes regarding freshness (as it has to inspect types for services), this causes issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants