The service container is the central building block around the new dependency injection based architecture of Drupal 8. Under normal conditions, a cached version of the service container class is read form the disk early in the request. It is then instantiated exactly once. This instance is used throughout the request, such that services can be composed and reused as necessary. This is the common pattern implemented by all Symfony DI-based web applications and frameworks.

However, Drupal deviates from this pattern under very special circumstances. Namely the container definition can be updated and the container instance is then replaced by a new container whenever a module is installed / uninstalled. This also happens often when executing tests (except PHPUnit tests).

When the container is rebuilt in the middle of a request, there is a chance that services instantiated before the rebuild have obsolete state. Even worse, they may depend on other obsolete services.

Throughout the development of Drupal 8, there have been attempts to work around this problem by implementing two techniques:

  1. Instances of services marked with the persist tag are restored after the container rebuild. Those services will automatically retain their state. However, as a consequence all dependencies of a persist service also need to be declared to be persistent.
  2. Recording on restoring state of some services is hard-coded into DrupalKernel::initializeContainer and some other places

Both of those workarounds are cumbersome and error-prone. While it is necessary to maintain a limited amount of state across container rebuilds, it is also vitally important that code triggering container rebuilds is designed in a way, such that it does not retain any references to outdated services. This fact should be documented somewhere.

Comments

donquixote’s picture

I share your concerns, but personally would prefer to go further than what you suggest.
But yes, if we don't fix this, e.g. in the way that i suggest in #2282217, then at least this flaw / source of unpredictability needs to be documented.

However, as a consequence all dependencies of a persist service also need to be declared to be persistent.

Not necessarily. We could use the observer pattern to tell the persisted services about updated dependencies.
Not trivial and not happening in current D8 afaik, but it is an option.
(Disclaimer: I personally prefer a solution where we don't have to care about this at all)

While it is necessary to maintain a limited amount of state across container rebuilds, it is also vitally important that code triggering container rebuilds is designed in a way, such that it does not retain any references to outdated services. This fact should be documented somewhere.

The form submit handler or other component that enables a module is still from the universe of the old container. And it generally still exists, and has control. The same for the services or components that called the submit handler. The call stack will unwind, all through obsolete services.

Usually this does not matter much, because request handling for form submit usually don't change due to newly enabled modules.
But I would prefer if we could rely more on predictable than on incidental work flows.

Future contrib modules may want to call module install on the fly, and then continue to work with the new container version immediately.
This would be discouraged by the new documentation you suggest, but is this enough?

Also, think about hooks or events that may be added that fire after a form submit handler, or after a drush operation, while the call stack is still polluted with obsolete services.

But imo it would be safer to have something like #2282217: [meta] Never replace the container while services are still in call stack., where it is going to be technically impossible to do this.
The control flow / call stack should go back to something that is not owned by a container, before any container rebuild stuff can happen.

donquixote’s picture

Btw, how do we deal with services that become obsolete outside of a container rebuild?
E.g. if the language changes?

jhodgdon’s picture

Status: Active » Postponed (maintainer needs more info)

What exactly are you advocating needs to be documented? And where should it be documented? Is this issue actionable?

znerol’s picture

cilefen’s picture

Title: Document the fact that it is not save to reuse services across container rebuilds » Document the fact that it is not safe to reuse services across container rebuilds

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.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.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.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.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.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.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should 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.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should 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.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should 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.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.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.

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

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should 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.

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

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

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

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should 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.

smustgrave’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

Since there hasn't been any movement since moving to PNMI 8 years ago moving to outdated

If you feel it's still an issue please feel free to reopen with an updated issue summary