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'.

Issue fork drupal-2896993

Command icon 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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

cburschka created an issue. See original summary.

cburschka’s picture

To 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.

cburschka’s picture

This might be fixed by the major change in #2531564: Fix leaky and brittle container serialization solution. But progress on that looks very stagnant.

cburschka’s picture

Issue summary: View changes
cburschka’s picture

(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.)

cburschka’s picture

Cursorily tested with the modules that triggered the error.

This definitely needs a kernel test case, especially with multiple decorators on the same service.

cburschka’s picture

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

cburschka’s picture

Bump. This bug still exists as of 8.8.6, and is still fixed by this patch.

cburschka’s picture

cburschka’s picture

Status: Needs review » Needs work

The last submitted patch, 16: 2896993-16.testonly.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

cburschka’s picture

Status: Needs work » Needs review

Expected failure.

jedihe’s picture

#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:

// Without #16
>>> $flood = \Drupal::service('flood');
=> Drupal\my_module\MyFlood {#9064}

// With #16
>>> $flood = \Drupal::service('flood');
=> Drupal\my_module\MyFlood {#11317
     +"_serviceId": "flood",
   }

// Temporarily exposed $innerService to peek into it.
>>> $flood->innerService;                                                                                                                                                                                                                                                                                            => Drupal\Core\Flood\DatabaseBackend {#9880
     +"_serviceId": "my_module.my_flood.inner",
   }

This is the decorated service definition:

  my_module.my_flood:
    class: Drupal\my_module\MyFlood
    public: false
    decorates: flood
    arguments: ['@my_module.my_flood.inner', '@database', '@request_stack']

Thanks a lot @cburschka! :)

andypost’s picture

It looks ready

cburschka’s picture

(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*)

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Related issues: +#2531564: Fix leaky and brittle container serialization solution

@cburschka well past you said

This definitely needs a kernel test case, especially with multiple decorators on the same service.

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.

cburschka’s picture

It'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. :)

The last submitted patch, 23: 2896993-23-testonly.patch, failed testing. View results

alexpott’s picture

It'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. :)

That's a good point.

Thanks for improving the test.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

It could be affected by https://github.com/symfony/symfony/pull/41407 which is included into latest 4.4.25 release

andypost’s picture

+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php
@@ -16,12 +16,34 @@ class DependencySerializationTraitPass implements CompilerPassInterface {
+      if (!$renamedId) {
+        $renamedId = $service_id . '.inner';

hardcoding the name is fragile approach

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mxr576’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

@andypost, re #29, isn't it what upstream also does? Or what is your expected solution here?

hardcoding the name is fragile approach

https://github.com/symfony/symfony/blob/eda7eb3cd8876e761fde46d65b0658a4...

After a year without a progress, I think it needs a reroll against 9.5.x.

cburschka’s picture

Status: Needs work » Needs review

Merged 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.

cburschka’s picture

Issue tags: -Needs reroll

Forgot to clear the reroll tag.

mxr576’s picture

Cool, let's hide "outdated" files from the issue description because the MR+the test only patch that get updated from now.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

Test added and fix looks great

alexpott’s picture

Version: 9.5.x-dev » 9.4.x-dev
Status: Reviewed & tested by the community » Fixed

Hopefully #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!

  • alexpott committed b16df24 on 10.1.x
    Issue #2896993 by cburschka, andypost, mxr576, jedihe: Decorated...

  • alexpott committed 4c126fd on 10.0.x
    Issue #2896993 by cburschka, andypost, mxr576, jedihe: Decorated...

  • alexpott committed c0cdaa7 on 9.5.x
    Issue #2896993 by cburschka, andypost, mxr576, jedihe: Decorated...

  • alexpott committed 1704f11 on 9.4.x
    Issue #2896993 by cburschka, andypost, mxr576, jedihe: Decorated...

Status: Fixed » Closed (fixed)

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