php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67913 mysqlnd ignores MYSQLI_OPT_CONNECT_TIMEOUT option
Submitted: 2014-08-26 22:55 UTC Modified: -
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (50.0%)
From: ablyler at barracuda dot com Assigned:
Status: Open Package: MySQL related
PHP Version: 5.5.16 OS: Any
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2014-08-26 22:55 UTC] ablyler at barracuda dot com
Description:
------------
The MYSQLI_OPT_CONNECT_TIMEOUT is ignored when using mysqlnd.  To reproduce this run:

netstat -l -p 9999

Then execute the included test script (wrapped with time).

Thanks to Jason Dictos for coming up with the fix to this.

Test script:
---------------
<?php

$connect_timeout = 5;
$resource = mysqli_init();

if (!mysqli_options($resource, MYSQLI_OPT_CONNECT_TIMEOUT, $connect_timeout))
{
   die('Unable to set connect timeout on resource');
}

var_dump(mysqli_real_connect($resource, '127.0.0.1', 'username', 'password', 'database', 9999));

Expected result:
----------------
It should return in ~5 seconds with errors.

Actual result:
--------------
The script will keep running past the timeout value.

Patches

mysqlnd-connection-timeout.patch (last revision 2014-08-26 22:56 UTC by ablyler at barracuda dot com)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-04-24 17:33 UTC] php at darkain dot com
This bug still persists in PHP 7.2.4. This is more than just a bug, it in effect DoSed a production system I manage. 

I run a series of MariaDB nodes in a Galera cluster. One of the nodes misbehaved. This happens from time to time. When a connection issue happens normally with a Galera node, it is pulled out of the local list of available nodes stored on each PHP instance. This process of storing and updating the list of Galera nodes is handled within a PHP script based on successful/failure to connect to each node. The problem is that even with MYSQLI_OPT_CONNECT_TIMEOUT set, no timeout happens if a successful TCP handshake is made but no data is transmitted over the wire afterwards. PHP is left in a hung state that can only be broken by restarting the entire PHP-FPM service. This leads to an eventual resource exhaustion within PHP-FPM hitting its maximum open connection limit as more users access the web site. This eventually breaks the entire web site.

Simple code to reproduce:

$sql = mysqli_init();
$sql->options(MYSQLI_OPT_CONNECT_TIMEOUT, 1);
$sql->real_connect('google.com:80', 'user', 'my_password', 'db');
echo 'GOOD';

NOTE that using a web server such as google.com, the server side will eventually break the connection. HOWEVER, the short timeout of 1 second never happens, and instead the server side breaks the connection after the server side timeout value. In the case of MariaDB with the single node that misbehaved, it never broke the connection. Instead, no data was ever transmitted over the wire after the TCP handshake, leaving PHP in an endless waiting process. Nothing after $sql->real_connect() is ever processed, therefor any sysadmin related emails about a failed connection or automatically pulling the failed node from the server pool ever happened as a result.
 [2018-06-18 23:02 UTC] php at darkain dot com
https://bugs.php.net/bug.php?id=76497

Solved by using the (currently undocumented) MYSQLI_OPT_READ_TIMEOUT option.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Fri Jul 19 23:01:25 2019 UTC