Bug #80546 [Opn]: Persistent connections appear open despite being closed
Edit report at https://bugs.php.net/bug.php?id=80546&edit=1
ID: 80546
Updated by: cmb@php.net
Reported by: jeremys at ha dot com
Summary: Persistent connections appear open despite being
closed
Status: Open
Type: Bug
Package: PDO DBlib
Operating System: RHEL 7.8
PHP Version: 7.3.25
Block user comment: N
Private report: N
New Comment:
Right, if check_liveness is (properly) implemented by the driver,
all is good. This is basically the same issue as bug #64603
(which is about PDO_Firebird).
However, apparently PDO doesn't require drivers to implement that
method, so I wonder whether the respective code for persistent
connections[1] shouldn't be generally changed:
if (!pdbh->methods->check_liveness || FAILURE ==
(pdbh->methods->check_liveness)(pdbh)) {
In words, if check_liveness is not implemented, assume the
connection to be dead.
[1] <https://github.com/php/php-src/blob/php-8.1.0alpha1/ext/pdo/pdo_dbh.c#L326>
Previous Comments:
------------------------------------------------------------------------
[2020-12-23 15:57:47] jeremys at ha dot com
Total copy/paste error on my part, PDO::ATTR_PERSISTENT should be set to true in the test script.
------------------------------------------------------------------------
[2020-12-22 21:17:33] jeremys at ha dot com
Description:
------------
Because PHP_DBLIB doesn't implement pdo_dbh_check_liveness_func (its value is null, which is
"equivalent to returning SUCCESS"), when instantiating a new PDO object using persistent
connections with dblib, if the connection dies, PHP is not aware of it and any subsequent queries
using the connection fail with "DBPROCESS is dead or not enabled".
pdo_dbh_check_liveness_func definition:
https://github.com/php/php-src/blob/caa710037e663fd78f67533b29611183090068b2/ext/pdo/php_pdo_driver.h#L264
pdo_dblib's implementation:
https://github.com/php/php-src/blob/caa710037e663fd78f67533b29611183090068b2/ext/pdo_dblib/dblib_driver.c#L417
In this specific example, a Microsoft SQL Server is used to simulate a connection timeout using the
WAITFOR DELAY query (which causes the connection to be considered dead by dblib). Connection is made
using FreeTDS 1.1.x.
Based on the source, seems to be an issue in PHP 8 as well.
Test script:
---------------
<?php
for( $i = 0; $i <= 1; $i++ )
{
$pdo = new PDO( 'dblib:dbname=northwinds;host=contoso', 'username',
'password', [
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_TIMEOUT => 5
] );
try
{
if( $i == 0 )
{
$pdo->query( "WAITFOR DELAY '00:00:10'" );
}
var_dump( $pdo->query( "SELECT 'output' AS Output" )->fetch(
PDO::FETCH_ASSOC )['Output'] );
}
catch( Throwable $e )
{
var_dump( stripos( $pdo->errorInfo()[2], 'DBPROCESS is dead or not enabled' )
=== 0 );
}
$pdo = null;
}
?>
Expected result:
----------------
bool(true)
string(6) "output"
Actual result:
--------------
bool(true)
bool(true)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=80546&edit=1
Thread (4 messages)