#47641 [Com]: mysql_connect() using TCP with connect_timeout not equal to -1
ID: 47641 Comment by: dima at dimych dot sumy dot ua Reported By: dima at dimych dot sumy dot ua Status: Feedback Bug Type: MySQL related Operating System: FreeBSD 7.1 PHP Version: 5.2.9 New Comment: ttyp3[r...@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[r...@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[r...@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[r...@noc-12:37:05]/home/dima# mysql -V mysql Ver 14.14 Distrib 5.1.32, for portbld-freebsd7.1 (i386) using 5.2 Previous Comments: [2009-06-02 08:34:17] j...@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-03-13 10:49:11] 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.c2008-11-14 18:37:28.0 +0200 +++ client.c.new2009-03-13 12:36:36.0 +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
#47641 [Com]: mysql_connect using TCP with connect_timeout not equal to -1
ID: 47641 Comment by: dima at dimych dot sumy dot ua Reported By: dima at dimych dot sumy dot ua Status: Open Bug Type: MySQL related Operating System: FreeBSD 7.1 PHP Version: 5.2.9 New Comment: 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.c2008-11-14 18:37:28.0 +0200 +++ client.c.new2009-03-13 12:36:36.0 +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