diff options
author | David Rothstein <drothstein@gmail.com> | 2012-12-08 18:31:33 -0500 |
---|---|---|
committer | David Rothstein <drothstein@gmail.com> | 2012-12-08 18:31:33 -0500 |
commit | c7e45d937d6ac63b2f4fc5a44ce3567159f86052 (patch) | |
tree | e84dd975f5eb7449fd927bd3d81087aff6192d3b /includes/database/database.inc | |
parent | ef10c14b7f0ddf5fb949083a34ddef5ebd2928f6 (diff) | |
download | brdo-c7e45d937d6ac63b2f4fc5a44ce3567159f86052.tar.gz brdo-c7e45d937d6ac63b2f4fc5a44ce3567159f86052.tar.bz2 |
Issue #843114 by sun, quicksketch, Berdir | c960657: Fixed DatabaseConnection::__construct() and DatabaseConnection_mysql()::__construct() leaks $this (Too many connections).
Diffstat (limited to 'includes/database/database.inc')
-rw-r--r-- | includes/database/database.inc | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/includes/database/database.inc b/includes/database/database.inc index cae50fb87..26ce6fcf4 100644 --- a/includes/database/database.inc +++ b/includes/database/database.inc @@ -194,7 +194,7 @@ abstract class DatabaseConnection extends PDO { /** * The key representing this connection. - * + * * The key is a unique string which identifies a database connection. A * connection can be a single server or a cluster of master and slaves (use * target to pick between master and slave). @@ -303,13 +303,29 @@ abstract class DatabaseConnection extends PDO { // Call PDO::__construct and PDO::setAttribute. parent::__construct($dsn, $username, $password, $driver_options); - // Set a specific PDOStatement class if the driver requires that. + // Set a Statement class, unless the driver opted out. if (!empty($this->statementClass)) { $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this))); } } /** + * Destroys this Connection object. + * + * PHP does not destruct an object if it is still referenced in other + * variables. In case of PDO database connection objects, PHP only closes the + * connection when the PDO object is destructed, so any references to this + * object may cause the number of maximum allowed connections to be exceeded. + */ + public function destroy() { + // Destroy all references to this connection by setting them to NULL. + // The Statement class attribute only accepts a new value that presents a + // proper callable, so we reset it to PDOStatement. + $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array())); + $this->schema = NULL; + } + + /** * Returns the default query options for any given query. * * A given query can be customized with a number of option flags in an @@ -1627,8 +1643,8 @@ abstract class Database { */ final public static function removeConnection($key) { if (isset(self::$databaseInfo[$key])) { + self::closeConnection(NULL, $key); unset(self::$databaseInfo[$key]); - unset(self::$connections[$key]); return TRUE; } else { @@ -1694,11 +1710,24 @@ abstract class Database { if (!isset($key)) { $key = self::$activeKey; } - // To close the connection, we need to unset the static variable. + // To close a connection, it needs to be set to NULL and removed from the + // static variable. In all cases, closeConnection() might be called for a + // connection that was not opened yet, in which case the key is not defined + // yet and we just ensure that the connection key is undefined. if (isset($target)) { + if (isset(self::$connections[$key][$target])) { + self::$connections[$key][$target]->destroy(); + self::$connections[$key][$target] = NULL; + } unset(self::$connections[$key][$target]); } else { + if (isset(self::$connections[$key])) { + foreach (self::$connections[$key] as $target => $connection) { + self::$connections[$key][$target]->destroy(); + self::$connections[$key][$target] = NULL; + } + } unset(self::$connections[$key]); } } @@ -1852,8 +1881,8 @@ class DatabaseTransaction { */ protected $name; - public function __construct(DatabaseConnection &$connection, $name = NULL) { - $this->connection = &$connection; + public function __construct(DatabaseConnection $connection, $name = NULL) { + $this->connection = $connection; // If there is no transaction depth, then no transaction has started. Name // the transaction 'drupal_transaction'. if (!$depth = $connection->transactionDepth()) { |