Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory/resource leaks in the wrapper connection #4515

Closed
morozov opened this issue Feb 27, 2021 · 3 comments · Fixed by #4517, #4516 or #4518
Closed

Memory/resource leaks in the wrapper connection #4515

morozov opened this issue Feb 27, 2021 · 3 comments · Fixed by #4517, #4516 or #4518

Comments

@morozov
Copy link
Member

morozov commented Feb 27, 2021

Q A
BC Break no
Version 2.12.1

If a wrapper connection is instantiated, establishes a driver-level connection and then is unreferenced, it doesn't get garbage-collected by PHP until GC kicks in (in the best case) and doesn't close the underlying connection.

Example 1
On each iteration, the previously instantiated connection should be destructed and close its driver connection but it isn't the case:

for ($i = 0; $i < 5; $i++) {
    $conn = DriverManager::getConnection([
        'driver' => 'pdo_pgsql',
        'host'   => 'localhost',
        'port'   => '5432',
        'user'   => 'postgres',
        'password' => 'Passw0rd',
        'dbname' => 'postgres',
    ]);

    echo $conn->fetchOne('SELECT SUM(numbackends) FROM pg_stat_database'), PHP_EOL;
}

// 1
// 2
// 3
// 4
// 5

Adding $conn->close() to the loop solves the problem however it doesn't do anything than removing the reference to the driver-level connection:

public function close()
{
$this->_conn = null;
}

This means that during iteration the object doesn't get destructed.

Example 2

There seems to be an internal circular reference between the wrapper and some of its components that doesn't let the connection to be destructed (see refcount=2):

$conn1 = DriverManager::getConnection([
    'driver' => 'pdo_pgsql',
]);
xdebug_debug_zval('conn1');
// conn1: (refcount=2, is_ref=0)=class Doctrine\DBAL\Connection { ... }

$conn2 = new stdClass();
xdebug_debug_zval('conn2');
// conn2: (refcount=1, is_ref=0)=class stdClass {  }
@morozov
Copy link
Member Author

morozov commented Feb 27, 2021

TADA!

$this->_expr = new Query\Expression\ExpressionBuilder($this);

This was referenced Feb 27, 2021
This was linked to pull requests Feb 27, 2021
@morozov morozov added this to the 4.0.0 milestone Feb 27, 2021
@morozov
Copy link
Member Author

morozov commented Feb 27, 2021

TADA!

$this->_schemaManager = $this->_driver->getSchemaManager($this);

@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
1 participant