Problem/Motivation

Running the SimpleTest Unit Tests in HHVM-nightly caused problems with regards to warnings complaining about "Too many arguments being passed to PDOStatement::execute". I initially thought that it was a bug with the way HHVM implements object subclassing and when a function with the same name but different signature was defined.

I debugged further, and found that the reason why Zend was succeeding was instead because there was an earlier exception raised that prevented SimpleTest from seeing a clean shutdown. To reproduce this: in includes/database/mysql/database.inc, go to function nextIdDelete(), in the catch block, add var_dump($e).

The problem seems to affect the MySQL driver mainly. During shutdown, DatabaseConnection_mysql::__destruct is called, which calls DatabaseConnection_mysql::nextIdDelete, but only after DatabaseConnection::destroy is called. This means two things:

  1. The PDO Statement class attribute has already been reset to PDOStatement; new prepared statements would therefore be of type PDOStatement
  2. Such statements do not have the DatabaseStatementInterface methods (fetchField et. al)

I note that DatabaseConnection_mysql::nextIdDelete uses fetchField (breaking condition #2 above), and the $this->query line would produce a PDOStatement (following condition #1 above). The code thus does not behave as expected.

Proposed resolution

Workarounds for the masses are, I believe, not currently needed. This is coming purely from a correctness standpoint, specifically when running unit tests (which only developers would do). In my case, it is also to improve HHVM compatibility with D7.

My current proposed solution does a few things:

  1. PHP5.5 (unsure about earlier versions) when setting PDO::ATTR_STATEMENT_CLASS back to PDOStatement, expects the attribute value to be array('PDOStatement') since its class constructor takes no arguments. This resolves the code path problem which silently made the test pass.
  2. DatabaseConnection::query will check that the query it is executing is a DatabaseStatementInterface before using the execute variant with the options argument. If it is a PDOStatement (as can be during shutdown) it will use the PDOStatement variant (without the $options argument)
  3. The DatabaseConnection_mysql::nextIdDelete function will only use PDO-variants of the functions, because it is called in the destructor.

Comments

lowjoel’s picture

lowjoel’s picture

Issue tags: +Stalking Crell
lowjoel’s picture

Berdir has suggested that this might apply to D8 too; let me know what you think and if it does I'll work to forward-port this.

sun’s picture

berdir’s picture

Version: 7.x-dev » 8.x-dev
Status: Needs review » Patch (to be ported)
Issue tags: +Needs backport to D7

Yes I'm pretty sure that this happens in 8.x too, I've seen segfaults the last time I've run run-tests.sh in 8.x. Let's verify, port the patch and fix it there first.

lowjoel’s picture

berdir’s picture

Status: Patch (to be ported) » Needs review

Status: Needs review » Needs work

The last submitted patch, 6: drupal-check-database-connections-objects-2216899-6-D8.patch, failed testing.

lowjoel’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 6: drupal-check-database-connections-objects-2216899-6-D8.patch, failed testing.

sun’s picture

+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
@@ -207,7 +207,7 @@ public function nextIdDelete() {
-      $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchField();
+      $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchColumn(0);

Somehow, that doesn't look right?

The query retrieves a single result set, and fetchField() just returns the first col of the first result row.


Perhaps more generally, the issue summary talks about a faulty invocation order of methods upon shutting down / destroying a connection — that doesn't appear to be attacked by this patch? Shouldn't we rather attack the root cause...?

lowjoel’s picture

Status: Needs work » Needs review

No, fetchColumn is correct: see the PHP docs

As it stands though, I don't think there's any way around this design issue without a larger, more involved rewrite. The problem here is that there are database queries during the database connection destruction sequence. Either we fix it in this manner, or somehow remove the need for database queries during destruction.

jhedstrom’s picture

+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -534,7 +534,11 @@ public function query($query, array $args = array(), $options = array()) {
+        if ($stmt instanceof DatabaseStatementInterface) {
+          $stmt->execute($args, $options);
+        } else {
+          $stmt->execute($args);
+        }

The else should be on a new line.

Also, the code pointed out in #11 works either way, and isn't really needed for the fix?

mgifford’s picture

Status: Needs review » Needs work

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
quietone’s picture

Status: Needs work » Closed (outdated)
Issue tags: +Bug Smash Initiative

This is about "Running the SimpleTest Unit Tests in HHVM-nightly" which is not supported.

Closing as outdated per #2165377-25: [meta] HHVM compatibility.

If that is wrong, reopen the issue, by setting the status to 'Active', and add a comment.

Thanks