Bug #71803 [Asn->Opn]: MySQLi doesn't properly update connection error with persistent connections
| From: | bjori@php.net | Date: | Mon, 09 Sep 2019 02:44:10 +0000 |
| Subject: | Bug #71803 [Asn->Opn]: MySQLi doesn't properly update connection error with persistent connections | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-222633@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=71803&edit=1
ID: 71803
Updated by: bjori@php.net
Reported by: jeff dot minard at creditkarma dot com
Summary: MySQLi doesn't properly update connection error with
persistent connections
-Status: Assigned
+Status: Open
Type: Bug
Package: MySQLi related
Operating System: CentOS
PHP Version: 5.6.19
-Assigned To: bjori
+Assigned To:
Block user comment: N
Private report: N
Previous Comments:
------------------------------------------------------------------------
[2017-03-21 00:24:43] domainadmin at digitalaxcess dot com
This happens also when script wants to create two separate mysqli connections.
Example:
$db_host1 = 'localhostinvalid';
$db_host2 = 'localhost';
$db_user = 'username';
$db_pass = 'password';
$db_name = 'dbname';
$db1 = @new mysqli($db_host1, $db_user, $db_pass, $db_name);
if ($db1->connect_errno) { echo $db1->connect_error.'<br/>'; } else { echo
'Ok<br/>';}
$db2 = @new mysqli($db_host2, $db_user, $db_pass, $db_name);
if ($db1->connect_errno) { echo $db1->connect_error.'<br/>'; } else { echo
'Ok<br/>';}
Result:
php_network_getaddresses: getaddrinfo failed: Name or service not known
Access denied for user 'username'@'localhost' (using password: YES)
$db1 will fail as it tries to connect to an invalid host, and the error message will indicate so.
Note that second "if" operates again on $db1, and the error message of
$db1->connect_error will be overwritten by whatever happened to $db2 (second connection), or if
$db2 connection was successful, $db1 will indicate the same even though $db1 wasn't successful
and "Ok" will be printed. Tested on 5.5 and 7.0.
------------------------------------------------------------------------
[2016-03-11 18:42:56] jeff dot minard at creditkarma dot com
Looks like the mysqli c code from here:
https://github.com/php/php-src/blob/71c19800258ee3a9548af9a5e64ab0a62d1b1d8e/ext/mysqli/mysqli_nonapi.c#L186
Will jump over this
https://github.com/php/php-src/blob/71c19800258ee3a9548af9a5e64ab0a62d1b1d8e/ext/mysqli/mysqli_nonapi.c#L259
Which means the errors don't get reset even though the "connect" call was successful.
------------------------------------------------------------------------
[2016-03-11 18:23:37] jeff dot minard at creditkarma dot com
Description:
------------
Essentially, it would appear that when creating a mysql connection, without persistence, each time
you call the mysqli_connect() method it will clear the "last error" state value so calls
to mysqli_connect_error() work correctly.
However, when you user presistent connections this doesn't work correctly. I suspect that the
mysqli_connect() method is, when doing persistence, shortcutting the method and not clearing the
state for what mysqli_connect_error() reads from. IE:
function mysqli_connect(...params) {
if (host is persistent) {
setup persistentHost
return true
}
clearErrorState()
doNormalConnectStuff()
}
As terrible psuedo code, I suspect that something like that is happening which causes the state to
not reset until the next real connection happens (instead of pulling an existing connection from the
pool).
Test script:
---------------
<?php
$mysql1 = '172.17.0.67';
$mysql2 = '172.17.0.69';
$conn = @mysqli_connect($mysql1, 'root', 'root', 'mysql',
'3306');
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
$conn = @mysqli_connect($mysql2, 'root', 'root', 'mysql',
'3307'); // note: WRONG PORT
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
$conn = @mysqli_connect($mysql1, 'root', 'root', 'mysql',
'3306');
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
$conn = @mysqli_connect($mysql2, 'root', 'root', 'mysql',
'3306');
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
$mysql1 = 'p:' . $mysql1;
$mysql2 = 'p:' . $mysql2;
$conn = @mysqli_connect($mysql1, 'root', 'root', 'mysql',
'3306');
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
$conn = @mysqli_connect($mysql2, 'root', 'root', 'mysql',
'3307'); // note: WRONG PORT
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
$conn = @mysqli_connect($mysql1, 'root', 'root', 'mysql',
'3306');
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
$conn = @mysqli_connect($mysql2, 'root', 'root', 'mysql',
'3306');
echo "Err?: " . ( $conn ? 'connected' : 'conn fail' ) . ' --
' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . "\n";
Expected result:
----------------
Err?: connected -- 0:
Err?: conn fail -- 2003: Can't connect to MySQL server on '172.17.0.69' (111)
Err?: connected -- 0:
Err?: connected -- 0:
Err?: connected -- 0:
Err?: conn fail -- 2003: Can't connect to MySQL server on '172.17.0.69' (111)
Err?: connected -- 0:
Err?: connected -- 0:
Actual result:
--------------
Err?: connected -- 0:
Err?: conn fail -- 2003: Can't connect to MySQL server on '172.17.0.69' (111)
Err?: connected -- 0:
Err?: connected -- 0:
Err?: connected -- 0:
Err?: conn fail -- 2003: Can't connect to MySQL server on '172.17.0.69' (111)
Err?: connected -- 2003: Can't connect to MySQL server on '172.17.0.69' (111)
Err?: connected -- 0:
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=71803&edit=1