laminas/laminas-db

persistent connection failures corrupts other unrelated DB connections

michalbundyra opened this issue · 1 comments

When a persistent connection fails to connect, other unrelated DB connections appear to fail when they are successfully connected - they should not falsely appear to fail.
Could be related to https://bugs.php.net/bug.php?id=69884 or https://bugs.php.net/bug.php?id=71803

PHP 5.6.14 (cli) (built: Dec 18 2015 14:17:39)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
with Xdebug v2.3.3, Copyright (c) 2002-2015, by Derick Rethans
with test_helpers v1.0.1-dev, Copyright (c) 2009-2013, by Johannes Schlueter, Scott MacVicar, Sebastian Bergmann

<?php
include 'vendor/autoload.php';

use Zend\Db\Adapter\Driver\Mysqli\Connection;

error_reporting(E_ERROR);              // Disable displaying warnings for this test.

$use_persistence = true;               // try this same test with false, and it will work without problems
$use_disconnect = true;                // this makes a difference
$use_same_variable_name_again = true;  // this seems to make a difference as well

$good_config = [
    'driver' => 'Mysqli',
    'database' => 'test',
    'username' => 'root',
    'password' => 'root',
    'host' => ($use_persistence ? 'p:' : '') . '127.0.0.1',
    'port' => '3306',
];

$good = new Connection($good_config);
$good->connect();

if ($use_disconnect) {
    $good->disconnect(); // no-op with persistence?
}

$bad_config = array_merge($good_config, ['port' => '3307']); // break the config intentionally

// Try to connect to the "bad" config (wrong port).

$bad = new Connection($bad_config);
try {
    $bad->connect(); // no exception thrown
} catch (\Exception $e) {
    // We expected this to fail with the bad config. But...
    var_dump($e->getMessage() == "Connection error");
}

// try to connect using the good config, shouldn't throw an exception (but due to a bug, it does)

if ($use_same_variable_name_again) {
    $good = new Connection($good_config);
    $good->connect();
} else {
    $good2 = new Connection($good_config);
    $good2->connect();
}

// Expected result: bool(true) with no exception thrown, in all cases

// Actual result:
//    persistence   disconnect    same variable         result
//    ------------- ------------- ---------------       ----------------
//    false         *             *                     no exception (correct behavior)
//    true          true          true                  exception (bug?)
//    true          false         true                  exception (bug?)
//    true          true          false                 exception (bug?)
//    true          false         false                 no exception (correct behavior)

Other variations of this test, including connecting to completely different database host IP addresses will exhibit the same "corrupted" error, which Zend Db uses to check that the connection was successful or not.

As a patch/workaround, I would recommend Zend Db not use the connection errno or error string to determine if the connection was successful or not, and instead rely on the return value of making a connection.


Originally posted by @thorie7912 at zendframework/zend-db#94

This package is considered feature-complete, and is now in security-only maintenance mode, following a decision by the Technical Steering Committee.
If you have a security issue, please follow our security reporting guidelines.
If you wish to take on the role of maintainer, please nominate yourself

If you are looking for an actively maintained package alternative, we recommend: