Problem/Motivation
Due to the introduction of closures in the constructor parameters in #3452414: Refactor storage class generation and #3560348: Improve handling of the 'in_trash' query parameter.
The following exception is thrown when certain elements are being serialized:
Serialization of 'Closure' is not allowed
I think normally the entity type manager should not be serialized (and instead classes referencing it should use the DependencySerializationTrait in order to serialize it), but the Trash entity type manager decorator doesn't serialize the internal core entity manager leading to this issue.
Steps to reproduce
In my particular instance, it happens on a clean site install, and in particular when webform_views triggers a call to the ElementInfoManager::buildInfo() which then tries to serialize the break_lock_link pre-render array and add it to the MemoryBackend.
Example closures being referenced:
[
0 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->entityDefinitionUpdateManager (Closure)',
1 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->entityLastInstalledSchemaRepository (Closure)',
2 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->trashHandlers->generator (Closure)',
3 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->alterHookListeners[entity_type][17][0]->trashManager->trashHandlers->count (Closure)',
4 => 'root[break_lock_link][#pre_render][0][0]->entityTypeManager->inner->handlers[views_data][block_content]->moduleHandler->hookImplementationLists[modules_installed]->listeners[18][0]->configFactory->eventDispatcher->listeners[kernel.request][500][0][0] (Closure)',
];
Proposed resolution
Until core supports serialization of [#AutowireServiceClosure] (and maybe #[AutowireIterator] in #3544994: Make service closures serializable in classes using DependencySerializationTrait, we need to manually ensure that the known services using closures (and referencing the entity type manager) can be serialized and unserialized as they may be referenced in certain hooks.
Remaining tasks
Provide MR.
User interface changes
N/A
| Comment | File | Size | Author |
|---|
Issue fork trash-3588477
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 #3
codebymikey commentedEnsure most of the services that may be potentially referenced as part of a pre-render hook are serializable.
edit: On further thought, given that core's
EntityTypeManagerwasn't serializable in the first place, I think the real issue might be because theTrashEntityTypeManagerhaspublic: false, so theReverseContaineris unable to resolve and instantiate it properly.Perhaps more thought might be necessary on the other services which also have the
public: falseproperty.Comment #4
codebymikey commentedAttached a static patch addressing the serialization issues - it also works as part of a clean site install.
Comment #6
amateescu commentedIt seems I went a bit overboard with cleanup and optimizations that are not properly supported by core yet :) However, instead of trying to make it work via custom __sleep/__wakeup implementations, I'd rather go back to using static instantiation when needed.
This looks ready to commit now, but I'll wait for a confirmation that my changes haven't introduced any new issues.
Comment #7
codebymikey commentedJust did a quick clean site install against the current MR (applied on top of the #3376216: Translation support issue fork) and unfortunately the current version still resulted in a crash on one of the nested closures:
I think there might be something special happening during the install phase causing it to be unable to resolve the newly decorated service. Making the decorated entity manager public gets past the closure serialization issue.
You can test this by :
1. Adding
trashto thestandardprofile's install list.2. Running
drush site-install standard -vvv --site-name=Trash test --db-url=sqlite://localhost/:memory: -y3. It should result in the unable to serialize 'Closure' exception.
Not sure if it's worth trying to add a test case for a profile installation.
Comment #8
amateescu commentedLooked into it and the problem is Drupal's
ReverseContainerwhich doesn't look at private services like Symfony does.Anyway, we need to make our decorator public at least until core steps up its game. Added a test as well because Trash is enabled by default on Drupal CMS, so it would good not to break it :)
Comment #10
amateescu commentedComment #11
amateescu commentedMerged into 3.1.x, thanks for finding and sticking with this issue!