To reproduce this error:
1. Decorate a service as documented in https://symfony.com/doc/current/service_container/service_decoration.html by defining a new service with public: false
and decorates: $oldServiceID$
. As an example, see the Redirect module which decorates the logger.factory service.
2. Create any class that references the service and try to serialize it (for example in a Form Builder on a form that uses the batch API, as seen in the Feeds module, which calls $this->logger()
and thereby stores a reference to the logger.factory service.
Expected result: DependencySerializationTrait identifies the loggerFactory variable as a service, and unloads it before serializing.
Actual: The loggerFactory object doesn't have a _serviceId variable as it is a "private service" which is skipped by the DependencySerializationTraitPass when the container is compiled, even though the "decorates" directive makes it replace a public service. As a result, DependencySerializationTrait doesn't recognize it as a service and unset it. And then it tries to serialize the container. Boom.
The best fix might be to make DependencySerializationTraitPass aware of service decoration: Check if service X decorates Y, and set X's _serviceId to Y while changing Y's _serviceId to 'X.inner'.
Comment | File | Size | Author |
---|---|---|---|
#23 | 2896993-23-testonly.patch | 3.55 KB | cburschka |
Issue fork drupal-2896993
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
cburschkaTo expand on this: Symfony's DecoratorServicePass is added as a PassConfig::TYPE_OPTIMIZE while Drupal's DependencySerializationTraitPass is added as PassConfig::TYPE_BEFORE_OPTIMIZATION, and therefore DSTP sets the serializable service IDs before DSP resolves decorations.
Changing it to run after optimization might fix the problem without requiring DSTP to explicitly handle decorators, but it may also cause a ton of other problems that I can't predict.
Comment #3
cburschkaThis might be fixed by the major change in #2531564: Fix leaky and brittle container serialization solution. But progress on that looks very stagnant.
Comment #4
cburschkaComment #5
cburschka(Of note: #2860496: Use DependencySerializationTrait in Redirect404LogSuppressor added a workaround to the Redirect module, so the bug can be reproduced only with 8.x-1.0-alpha4.)
Comment #6
cburschkaCursorily tested with the modules that triggered the error.
This definitely needs a kernel test case, especially with multiple decorators on the same service.
Comment #7
cburschkaI see now that this bug was actually discovered half a year ago, and then closed in favor of #2531564: Fix leaky and brittle container serialization solution.
#2536370: DependencySerializationTraitPass does not add _serviceId to decorated services
Comment #14
cburschkaBump. This bug still exists as of 8.8.6, and is still fixed by this patch.
Comment #15
cburschkaAdding a kernel test for this patch.
Comment #16
cburschkaComment #18
cburschkaExpected failure.
Comment #19
jedihe CreditAttribution: jedihe commented#16 is working for me, running Drupal 8.8.6; before the patch, a decorated 'flood' service was being serialized this way (separate of the _serviceIds array for its nesting level):
...{s:8:" * flood";O:22:"Drupal\my_module\MyFlood":2:{s:14:" * _serviceIds";a:3:{s:12:"innerService";s:5:"flood";s:10:"connection";s:8:"database";s:12:"requestStack";s:13:"request_stack";}...
After I applied the patch, the decorated flood service is now part of the "_serviceIds" array:
...s:14:" * _serviceIds";a:10:{s:14:"entity_manager";s:14:"entity.manager";s:6:"client";s:16:"my_module.api_client";s:15:"my_module_user_manager";s:18:"my_module.user_manager";s:15:"email_validator";s:15:"email.validator";s:5:"flood";s:5:"flood";s:8:"renderer";s:8:"renderer";s:15:"someService";s:20:"some.service";s:12:"requestStack";s:13:"request_stack";s:13:"configFactory";s:14:"config.factory";s:17:"stringTranslation";s:18:"string_translation";}...
Also, using drush php:cli shows proper behavior now:
This is the decorated service definition:
Thanks a lot @cburschka! :)
Comment #20
andypostIt looks ready
Comment #21
cburschka(I'm glad it still works, but tbh I hope I knew what I was doing with that priority queue back then, because darn if I can remember how it works after all this time. *sweating*)
Comment #22
alexpott@cburschka well past you said
And the current test does not have that so... back to needs work. It might be good to push on #2531564: Fix leaky and brittle container serialization solution as the better fix.
Comment #23
cburschkaIt's true that the other issue will make this fix obsolete when it's done, but it's not yet clear if it'll be possible to push it to D8 or if it will end up requiring deprecations, so this smaller bugfix might still be worthwhile. :)
Comment #25
alexpottThat's a good point.
Thanks for improving the test.
Comment #28
andypostIt could be affected by https://github.com/symfony/symfony/pull/41407 which is included into latest 4.4.25 release
Comment #29
andyposthardcoding the name is fragile approach
Comment #32
mxr576@andypost, re #29, isn't it what upstream also does? Or what is your expected solution here?
https://github.com/symfony/symfony/blob/eda7eb3cd8876e761fde46d65b0658a4...
After a year without a progress, I think it needs a reroll against 9.5.x.
Comment #34
cburschkaMerged 9.5.x (no conflicts, simple FF) into my branch and made a merge request.
Rerolled patch file against 9.5.x is still byte-identical to #23, so no need to upload it again. :D
Queued a new test for the test-only patch against 9.5.x, since the issue fork can't do that.
Comment #35
cburschkaForgot to clear the reroll tag.
Comment #36
mxr576Cool, let's hide "outdated" files from the issue description because the MR+the test only patch that get updated from now.
Comment #37
andypostTest added and fix looks great
Comment #38
alexpottHopefully #2531564: Fix leaky and brittle container serialization solution will make some progress someday. As it has not for now lets get this done...
Committed and pushed b16df24b08 to 10.1.x and 4c126fd390 to 10.0.x and c0cdaa7151 to 9.5.x and 1704f1191d to 9.4.x. Thanks!