Updated: Comment 0

Problem/Motivation

A short description of synchronized services:

some special services aren't constructed via DI though they come from outside
as existing instances of the services might already have an instance of that special service injected you can automatically call setters on the other services
so everytime you do $container->set('request', $request); all services with a setRequest are called.

Synchronized services work fine once we have the container on disk, though in a simpletest enviroment we construct one via the ContainerBuild class. Drupal
has overridden the set() method on there in order to not cause failues on already compiled containers, though we skip the code to sync services completly:

        if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized()) {
            $this->synchronize($id);
        }

Proposed resolution

  • copy over the code for synchronized services
  • Also copy some of the tests so we are sure that services are synchronized.

Remaining tasks

User interface changes

API changes

CommentFileSizeAuthor
#1 container_builder-2147451.patch3.9 KBdawehner
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

Status: Active » Needs review
FileSize
3.9 KB

Here is a patch as well as a test. It is not trivial to reuse any code of symfony.

Status: Needs review » Needs work

The last submitted patch, 1: container_builder-2147451.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review

1: container_builder-2147451.patch queued for re-testing.

chx’s picture

Status: Needs review » Reviewed & tested by the community

Until we give up this fantasy of working with projects outside of Drupal and just edit them for our betterment we do not have a better recourse here than to copy-paste wads of code. (See https://drupal.org/comment/8291069#comment-8291069 for a better workflow.)

webchick’s picture

Is there an upstream patch for this?

dawehner’s picture

@webchick
That is a bit difficult as setting a service on a frozen container is more a bug in our code than in the bug of symfony. Sadly fixing this potentially requires changes all over the place (installer/simpletest).

xjm’s picture

1: container_builder-2147451.patch queued for re-testing.

webchick’s picture

Status: Reviewed & tested by the community » Needs work

Ok, after spending some time trawling through a diff of core/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerBuilder.php and core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php I think I see. So we're already overriding Symfony's set() method on this class, but haven't copied in the code about frozen containers.

FWIW, it seems like Symfony might've fixed this upstream since we forked ContainerBuilder into core/lib/Drupal. Or at least https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Dep... seems to indicate that it's ok to add services to frozen containers these days. I fired up #2163795: Possible alternative to #2147451? out of curiosity, to see what would happen if we just remove our override of set() altogether instead. It will probably fail.

I'm still mystified, however, as to what the major bug is here and how the test proves we've fixed it. :\ We need to improve the docs here to be explicit about why we're doing this, and how we will know we can remove the hack in the future. (i.e. a @todo pointing to a specific issue about cleaning this up)

dawehner’s picture

@webchick ... this hunk you look at, was changed when sychronized services got added.
This code still assumes that you CANNOT set arbitrary services on frozen container builders ...

I'm still mystified, however, as to what the major bug is here

I consider everything on the container as potential major too be honest. The other thin is: tests don't work as expected which cause potentially wrong written tests and so wrong functionality (yes we have seen that on some issue).

Not sure whether I have the motivation to update the patch

dawehner’s picture

Status: Needs work » Reviewed & tested by the community

You know, we have docs for everything already:

* Drupal's container builder can be used at runtime after compilation, so we
* override Symfony's ContainerBuilder's restriction on setting services in a
* frozen builder.

* @todo Submit upstream patches to Symfony to not require these overrides.

catch’s picture

Assigned: Unassigned » webchick

I think this is OK. Moving back to webchick for feedback.

webchick’s picture

Assigned: webchick » Unassigned

I already explained in #8 I have absolutely no idea what this is doing. So either we fix the docs so that I do understand, or some other core committer commits this. :)

webchick’s picture

Daniel helpfully gave this explanation in IRC:

"You might have services which changes during the runtime of a request (the current logged in user is one example). After changing the logged in user, there might be services with an instance of the old one stored. synchronized services are getting synched/updates automatically by calling some method like setCurrentUser() on all these other services"

I'll see if I can get a quiet moment this evening or tomorrow to parse that and adjust whatever docs accordingly, but I honestly don't think it's worth holding this patch up on me.

Dries’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 8.x. Thank.

dawehner’s picture

Given that this just fixed an internal bug there is no real need for a change notice (just wanted to be sure noone asks for one).

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.