Problem/Motivation
* 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 Restrict this to synthetic services only. Ideally, the upstream
* ContainerBuilder class should be fixed to allow setting synthetic
* services in a frozen builder.
This doesn't seem to have gotten a follow up issue and is orphaned and never addressed. Shortly after this was added almost 10 years ago to hack around Synfony, Symfony addressed the bug so its been forgotten a long long time.
#1711492: Clarify why Drupal requires a custom ContainerBuilder
https://github.com/symfony/symfony/pull/6500
Unfortunately this means we might have a sort of accidental defacto feature despite the possible problems it introduces. The point of having a compiled container is that there is some safety provided about the consistency of the environment. This is why we rebuild compiled containers instead of just mangling them with updates.
Possibly a different issue and probably more dangerous, we continued this concept out of the Builder into the compiled container which has no mutation protection allowing objects instantiated at different times to have completely different services injected.
Steps to reproduce
ContainerBuilder is probably mostly the TODO. Since we only use the builder during install, updates, and other places we're rebuilding the container, it should generally be difficult to even try to modify the compiled container.
Proposed resolution
1) Fix container builder to use parent builder with BC just in case.
2) Follow up with container fixes?
Remaining tasks
Investigate impact
Postponed on #2368263: Remove the persist service tag
User interface changes
n/a
API changes
TBD
Data model changes
n/a
Release notes snippet
TBD
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | 3300306-12.patch | 3.89 KB | andypost |
Comments
Comment #2
andypostExactly this changes requested in #2937010-14: Bring ContainerBuilder inline with Symfony Container and apply upstream improvements
Comment #3
andypostComment #4
neclimdulAh ha. I was digging around patches and the meta issues but either missed that issue somehow or missed alex bringing it up in the reviews. I'll make a patch and see the impact. If its pretty trivial we can maybe toss it back over there.
Comment #5
neclimdulSo took a lot of back and forth yesterday with chx on slack to step through some seemingly unrelated changes required for this. Going to post a patch to kick off some tests then explain in a review.
Comment #6
neclimdulUpdating the doc block made it clear this was never documented. Went ahead and included some docs but it looks to be cruft that could even get in the way and should probably be removed. If we want to continue to have a standard we should use static analysis to enforce it.
I could have copied the checks from symfony but this seemed maybe the best way to avoid keeping in sync with any bug fix or improvements happening up stream which is the intention. If we did this in 9 for 10 the maintenance wouldn't matter as much and copying the logic would probably be better. I don't know why I said static, I meant synthetic.
This is required by cause Symfony's container builder removes the definition if you unset the service. This is a feature of it being a _builder_ so this hack doesn't work anymore. Why was this hack here and why don't we need it anymore? Stick around for a tale...
First the reason for it existing. Without this line, the entire _serviceId sleep magic falls apparent and we suddenly start serializing database connections.
You might be asking how could that possibly be? This has nothing to do with serialization right?
Well our first clue is just above this change we can see the code ask the container to create the database connection but to see why we have to look at another change.
Now is where this weird change comes in. See that database driver creation happens in a compile pass before the "DependencySerializationTraitPass" has run. That means our service container doesn't have the magic that tricks Symfony into writing _serviceId onto the object. Which mean our connection doesn't have one and the house of cards collapses.
This particular change should probably not be committed as is because we have a better fix of removing the pass entirely in #2531564: Fix leaky and brittle container serialization solution but for things to generally work for testing this is needed.
Comment #8
andypostIt looks awesome! Please add code comment why this compiler pass running there to prevent further confusion
Comment #9
andypostThe winner is
91x: Setting service "request_stack" for an unknown or non-synthetic service definition on a compiled container is not allowed. Doing so is deprecated in drupal:10.0.0 and the method is removed in drupal:11.0.0. Make service static or refactor service usage. See https://www.drupal.org/node/3300306Comment #10
neclimdulOh yeah, I forgot about that. um... there's an issue to remove the persist tag on request services. Attached
So, I think the right way to handle this might be postpone this on the better fixes for some of the underlying issues and working with the BC they add.
Comment #11
andypostI bet the issue is #2368263: Remove the persist service tag
Comment #12
andypostre-roll after #2937010: Bring ContainerBuilder inline with Symfony Container and apply upstream improvements
Comment #14
andypostSo the same 3 services!
Comment #15
andypostLooks mostly it will be fixed after #2368263: Remove the persist service tag
Comment #17
mstrelan commentedLet's postpone this on #2368263: Remove the persist service tag then. I don't see any changes to system.module either so changed the component to base system.