Problem
Upstream issue: https://bugs.xdebug.org/view.php?id=2222
Drupal does auto-commit transactions on shutdown, as discussed at #1608374: Database autocommit disabling at shutdown. At the moment, quite some code relies on that behavior.
For that to work, Drupal\Core\Database\Transaction::__destruct
must run before Drupal\mysql\Driver\Database\mysql\Connection::__destruct
. If the order is reversed, this results in nasty fatal errors like the following:
Fatal error: Uncaught Error: Call to a member function inTransaction() on null in /var/www/web/core/modules/mysql/src/Driver/Database/mysql/Connection.php on line 483
Error: Call to a member function inTransaction() on null in /var/www/web/core/modules/mysql/src/Driver/Database/mysql/Connection.php on line 483
Call Stack:
15.7059 86985504 1. Drupal\Core\Database\Transaction->__destruct() /var/www/web/core/lib/Drupal/Core/Database/Transaction.php:0
15.7059 86985504 2. Drupal\Core\Database\Connection->popTransaction($name = 'drupal_transaction') /var/www/web/core/lib/Drupal/Core/Database/Transaction.php:71
15.7059 86985504 3. Drupal\mysql\Driver\Database\mysql\Connection->popCommittableTransactions() /var/www/web/core/lib/Drupal/Core/Database/Connection.php:1447
15.7059 86985880 4. Drupal\mysql\Driver\Database\mysql\Connection->doCommit() /var/www/web/core/modules/mysql/src/Driver/Database/mysql/Connection.php:415
As a result the transaction is not committed. In our project, this suddenly (=zero change) popped up and reliable killed every "drush cr" or simple drush commands like "drush user:unblock".
According to https://www.php.net/manual/en/language.oop5.decon.php the object destruction order during shutdown is random:
PHP possesses a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.
Steps to reproduce
Unclear.
We ran into this at drunomics on a rather large project, on CI builds, suddenly without changes to code or the docker-controlled environment. The error only happened during CLI invocations, but was reproducable also without drush.
It turns out that most of the time the object destruction order is correct and no problems arise. But somehow for CLI invocations the order can become reliable different, thus causing the problem.
Proposed resolution
Do not rely on a object destruction order that is a random. Make code work in both situations, regardless which one runs first.
Note: This appear on 10.1.x-dev so first we need to verify whether the problem can happen on 10.2.x-dev as well, since there is a new transaction manager.
Workarounds
- ensure that develop is not in your xdebug.mode value
- pin xdebug in CI image to xdebug 3.2.2
API changes
-
Data model changes
-