php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47641 mysql_connect() using TCP with connect_timeout not equal to -1
Submitted: 2009-03-13 10:31 UTC Modified: 2009-06-10 01:00 UTC
Votes:1
Avg. Score:1.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: dima at dimych dot sumy dot ua Assigned:
Status: No Feedback Package: MySQL related
PHP Version: 5.2.9 OS: FreeBSD 7.1
Private report: No CVE-ID: None
 [2009-03-13 10:31 UTC] dima at dimych dot sumy dot ua
Description:
------------
connecting to mysql server using TCP 
with mysql.connect_timeout set not equal to "-1" in php.ini produces error:
Can't connect to MySQL server on '127.0.0.1' (0)


Reproduce code:
---------------
1 in php.ini set:
   mysql.connect_timeout = 60

2 create user test with password test in local database

3 create file test.php:
<?php
mysql_connect("127.0.0.1", 'test', 'test');
?>

Expected result:
----------------
Successful connection to database like for:
<?php
mysql_connect("localhost", 'test', 'test');
?>
or connection to 127.0.0.1 with mysql.connect_timeout = -1




Actual result:
--------------
PHP Warning:  mysql_connect(): Can't connect to MySQL server on '127.0.0.1' (0) in /usr/home/dima/test.php on line 2


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-03-13 10:49 UTC] dima at dimych dot sumy dot ua
I`m investigated this bug using mysql client trace file.
For additional debug info I modified mysql client library file 
sql-common/client.c. Modifications done in functions mysql_options, my_connect, wait_for_data. This is diff for source of modified functions (need for understanding new trace data):
--- client.c    2008-11-14 18:37:28.000000000 +0200
+++ client.c.new        2009-03-13 12:36:36.000000000 +0200
@@ -143,7 +143,14 @@
 int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
               uint timeout)
 {
+  DBUG_ENTER("my_connect");
+  DBUG_PRINT("enter", ("socket: %d name:{%d,%d,[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d]} namelen: %lu timeout: %lu",

+                       fd, timeout, name->sa_len, name->sa_family, name->sa_data[0], name->sa_data[1],
+                       name->sa_data[2],name->sa_data[3],name->sa_data[4],name->sa_data[5],name->sa_data[6],
+                       name->sa_data[7],name->sa_data[8],name->sa_data[9],name->sa_data[10],name->sa_data[11],
+                       name->sa_data[12],name->sa_data[13],namelen,timeout));
 #if defined(__WIN__) || defined(__NETWARE__)
+  DBUG_RETURN(0);
   return connect(fd, (struct sockaddr*) name, namelen);
 #else
   int flags, res, s_err;
@@ -153,11 +160,14 @@
     exactly like the normal connect() call does.
   */

-  if (timeout == 0)
+  if (timeout == 0) {
+    DBUG_PRINT("info", ("timeout == 0"));
+    DBUG_RETURN(0);
     return connect(fd, (struct sockaddr*) name, namelen);
-
+  }
   flags = fcntl(fd, F_GETFL, 0);         /* Set socket to not block */
 #ifdef O_NONBLOCK
+  DBUG_PRINT("info", ("O_NONBLOCK"));
   fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
 #endif

@@ -167,10 +177,15 @@
   if ((res != 0) && (s_err != EINPROGRESS))
   {
     errno= s_err;                      /* Restore it */
+    DBUG_PRINT("error", ("res != 0. res: %d errno: %d", res, errno));
+    DBUG_RETURN(-1);
     return(-1);
   }
-  if (res == 0)                                /* Connected quickly! */
+  if (res == 0)                                /* Connected quickly! */ {
+    DBUG_PRINT("info", ("res == 0"));
+    DBUG_RETURN(0);
     return(0);
+  }
   return wait_for_data(fd, timeout);
 #endif
 }
@@ -187,7 +202,10 @@

 static int wait_for_data(my_socket fd, uint timeout)
 {
+  DBUG_ENTER("wait_for_data");
+  DBUG_PRINT("enter", ("timeout :%lu", timeout));
 #ifdef HAVE_POLL
+  DBUG_PRINT("info:", ("wait using poll"));
   struct pollfd ufds;
   int res;

@@ -196,20 +214,30 @@
   if (!(res= poll(&ufds, 1, (int) timeout*1000)))
   {
     errno= EINTR;
+    DBUG_PRINT("error:", ("EINTR"));
+    DBUG_RETURN(-1);
     return -1;
   }
-  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
+  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI))) {
+    DBUG_PRINT("error:", ("res < 0"));
+    DBUG_RETURN(-1);
     return -1;
+  }
+  DBUG_RETURN(0);
   return 0;
 #else
+  DBUG_PRINT("info:", ("wait using loop"));
   SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
   fd_set sfds;
   struct timeval tv;
   time_t start_time, now_time;
   int res, s_err;

-  if (fd >= FD_SETSIZE)                                /* Check if wrong error */
+  if (fd >= FD_SETSIZE) {                              /* Check if wrong error */
+  DBUG_PRINT("info:", ("wait using loop"));
+    DBUG_RETURN(0);
     return 0;                                  /* Can't use timeout */
+  }

   /*
     Our connection is "in progress."  We can use the select() call to wait
@@ -252,8 +280,11 @@
       return -1;
     now_time= my_time(0);
     timeout-= (uint) (now_time - start_time);
-    if (errno != EINTR || (int) timeout <= 0)
+    if (errno != EINTR || (int) timeout <= 0) {
+      DBUG_PRINT("error:", ("errno != EINTR. errno: %d", errno));
+      DBUG_RETURN(-1);
       return -1;
+    }
   }

   /*
@@ -263,14 +294,19 @@
   */

   s_err=0;
-  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
+  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) {
+    DBUG_PRINT("error:", ("getscokopt"));
+    DBUG_RETURN(-1);
     return(-1);
-
+  }
   if (s_err)
   {                                            /* getsockopt could succeed */
     errno = s_err;
+    DBUG_PRINT("error:", ("getsockopt errno: %d", errno));
+    DBUG_RETURN(-1);
     return(-1);                                        /* but return an error... */
   }
+  DBUG_RETURN(0);
   return (0);                                  /* ok */
 #endif /* HAVE_POLL */
 }
@@ -3023,6 +3059,7 @@
   DBUG_PRINT("enter",("option: %d",(int) option));
   switch (option) {
   case MYSQL_OPT_CONNECT_TIMEOUT:
+  DBUG_PRINT("enter",("arg: %lu",*(uint*) arg));
     mysql->options.connect_timeout= *(uint*) arg;
     break;
   case MYSQL_OPT_READ_TIMEOUT:

--- END OF DIFF ---
doing connect using
<?php mysql_connect("127.0.0.1", 'test', 'test'); ?>

trace file contains this:
>mysql_option
| enter: option: 0
| enter: arg: 60
<mysql_option
>mysql_real_connect
| enter: host: 127.0.0.1  db: (Null)  user: test
| info: Server name: '127.0.0.1'.  TCP sock: 3306
| >vio_new
| | enter: sd: 4
| | >my_malloc
| | | my: size: 152  my_flags: 16
| | | exit: ptr: 0x2972c340
| | <my_malloc
| | >vio_init
| | | enter: type: 1  sd: 4  flags: 2
| | | >my_malloc
| | | | my: size: 16384  my_flags: 16
| | | | exit: ptr: 0x297c6000
| | | <my_malloc
| | <vio_init
| <vio_new
| >my_connect
| | enter: socket: 4 name:{60,0,[2,12,-22,127,0,0,1,0,0,0,0,0,0,0]} namelen: 0 timeout: 16
| | info:: O_NONBLOCK
| | error:: res != 0. res: -1 errno: 0
| <my_connect
| error: Got error 0 on connect to '127.0.0.1'
| >set_mysql_extended_error
| | enter: error :2003 'Can't connect to MySQL server on '%-.100s' (%d)'
| <set_mysql_extended_error
| error: message: 2003/HY000 (Can't connect to MySQL server on '127.0.0.1' (0))
| >end_server

--- END OF TRACE FILE ---
Doing connect with command line utility "mysql":
mysql -u test -ptest -h 127.0.0.1 --connect_timeout=60 --debug=d:t:O,/tmp/client.trace

Trace file contains:
| >my_malloc
| | my: size: 16  my_flags: 16
| | exit: ptr: 0x2840e050
| <my_malloc
| >my_malloc
| | my: size: 520  my_flags: 16
| | exit: ptr: 0x28410000
| <my_malloc
| >my_malloc
| | my: size: 512  my_flags: 48
| | exit: ptr: 0x2842f200
| <my_malloc
| >init_alloc_root
| | enter: root: 0x805f968
| <init_alloc_root
| >init_alloc_root
| | enter: root: 0x805f9a0
| <init_alloc_root
| >mysql_option
| | enter: option: 0
| | enter: arg: 60
| <mysql_option
| >mysql_real_connect
| | enter: host: 127.0.0.1  db: (Null)  user: test
| | info: Server name: '127.0.0.1'.  TCP sock: 3306
| | >vio_new
| | | enter: sd: 4
| | | >my_malloc
| | | | my: size: 152  my_flags: 16
| | | | exit: ptr: 0x284280c0
| | | <my_malloc
| | | >vio_init
| | | | enter: type: 1  sd: 4  flags: 2
| | | | >my_malloc
| | | | | my: size: 16384  my_flags: 16
| | | | | exit: ptr: 0x28437000
| | | | <my_malloc
| | | <vio_init
| | <vio_new
| | >my_connect
| | | enter: socket: 4 name:{60,0,[2,12,-22,127,0,0,1,0,0,0,0,0,0,0]} namelen: 0 timeout: 16
| | | info:: O_NONBLOCK
| | | >wait_for_data
| | | | enter: timeout :60
| | | | info:: wait using poll
| | | <wait_for_data
| | | >my_net_init

--- END OF TRACE FILE ---
setting mysql.connect_timeout = -1 in php.ini and doing connect using
<?php mysql_connect("127.0.0.1", 'test', 'test'); ?>

trace file contains this:
>mysql_real_connect
| enter: host: 127.0.0.1  db: (Null)  user: test
| info: Server name: '127.0.0.1'.  TCP sock: 3306
| >vio_new
| | enter: sd: 4
| | >my_malloc
| | | my: size: 152  my_flags: 16
| | | exit: ptr: 0x2972c340
| | <my_malloc
| | >vio_init
| | | enter: type: 1  sd: 4  flags: 2
| | | >my_malloc
| | | | my: size: 16384  my_flags: 16
| | | | exit: ptr: 0x297c6000
| | | <my_malloc
| | <vio_init
| <vio_new
| >my_connect
| | enter: socket: 4 name:{0,0,[2,12,-22,127,0,0,1,0,0,0,0,0,0,0]} namelen: 0 timeout: 16
| | info:: timeout == 0
| <my_connect
| >my_net_init

--- END OF TRACE FILE ---
 [2009-06-02 08:34 UTC] jani@php.net
Exactly what mysql version are you trying this with? As for me it works 
perfectly fine with PHP compiled with Mysql 5.0.37 client lib.

Tried with:

# php -n -d mysql.connect_timeout=60 -r 'mysql_connect("127.0.0.1", 
"test", "");'

 [2009-06-02 10:06 UTC] dima at dimych dot sumy dot ua
ttyp3[root@noc-12:35:15]/home/dima# php -n -d mysql.connect_timeout=60 -r 'mysql_connect("127.0.0.1", "test", "");'

Fatal error: Call to undefined function mysql_connect() in Command line code on line 1

ttyp3[root@noc-12:35:19]/home/dima# php -d mysql.connect_timeout=60 -r 'mysql_connect("127.0.0.1", "test", "");'
PHP Warning:  mysql_connect(): Can't connect to MySQL server on '127.0.0.1' (0) in Command line code on line 1

ttyp3[root@noc-12:36:17]/home/dima# php -d mysql.connect_timeout=60 -r 'mysql_connect("localhost", "test", "");'
PHP Warning:  mysql_connect(): Access denied for user 'test'@'localhost' (using password: NO) in Command line code on li
ne 1

ttyp3[root@noc-12:37:05]/home/dima# mysql -V
mysql  Ver 14.14 Distrib 5.1.32, for portbld-freebsd7.1 (i386) using  5.2
 [2009-06-10 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 12:01:31 2024 UTC