List:Commits« Previous MessageNext Message »
From:Magnus Blåudd Date:April 15 2010 11:38am
Subject:bzr commit into mysql-5.1-telco-7.0 branch (magnus.blaudd:3498)
Bug#37267 Bug#44344
View as plain text  
#At file:///home/msvensson/mysql/7.0-stb-bug44344/ based on revid:magnus.blaudd@stripped172450-31h4cmkycgqz8li9

 3498 Magnus Blåudd	2010-04-15
      Bug#44344  Backport BUG#37267 connect() EINPROGRESS failures mishandled in client library
      - backport of patch for bug#37267 to fix problem in 'mysql_real_connect'
        which didn't always try connecting through all the addresses
        returned from 'getaddrinfo'

    modified:
      libmysqld/libmysqld.c
      mysql-test/include/wait_for_slave_param.inc
      sql-common/client.c
=== modified file 'libmysqld/libmysqld.c'
--- a/libmysqld/libmysqld.c	2009-12-18 06:43:04 +0000
+++ b/libmysqld/libmysqld.c	2010-04-15 11:38:10 +0000
@@ -100,7 +100,7 @@ mysql_real_connect(MYSQL *mysql,const ch
   char name_buff[USERNAME_LENGTH];
 
   DBUG_ENTER("mysql_real_connect");
-  DBUG_PRINT("enter",("host: %s  db: %s  user: %s",
+  DBUG_PRINT("enter",("host: %s  db: %s  user: %s (libmysqld)",
 		      host ? host : "(Null)",
 		      db ? db : "(Null)",
 		      user ? user : "(Null)"));

=== modified file 'mysql-test/include/wait_for_slave_param.inc'
--- a/mysql-test/include/wait_for_slave_param.inc	2009-01-09 14:12:31 +0000
+++ b/mysql-test/include/wait_for_slave_param.inc	2010-04-15 11:38:10 +0000
@@ -49,6 +49,8 @@ if (!$_slave_timeout_counter)
 {
   let $_slave_timeout_counter= 3000;
 }
+# Save resulting counter for later use.
+let $slave_tcnt= $_slave_timeout_counter;
 
 let $_slave_param_comparison= $slave_param_comparison;
 if (`SELECT '$_slave_param_comparison' = ''`)
@@ -70,7 +72,7 @@ while (`SELECT NOT('$_show_slave_status_
 # This has to be outside the loop until BUG#41913 has been fixed
 if (!$_slave_timeout_counter)
 {
-  --echo **** ERROR: timeout after $slave_timeout seconds while waiting for slave parameter $slave_param $_slave_param_comparison $slave_param_value ****
+  --echo **** ERROR: timeout after $slave_tcnt deci-seconds while waiting for slave parameter $slave_param $_slave_param_comparison $slave_param_value ****
   if (`SELECT '$slave_error_message' != ''`)
   {
     --echo Message: $slave_error_message

=== modified file 'sql-common/client.c'
--- a/sql-common/client.c	2010-04-13 16:01:38 +0000
+++ b/sql-common/client.c	2010-04-15 11:38:10 +0000
@@ -147,9 +147,12 @@ int my_connect(my_socket fd, const struc
 	       uint timeout)
 {
 #if defined(__WIN__) || defined(__NETWARE__)
-  return connect(fd, (struct sockaddr*) name, namelen);
+  DBUG_ENTER("my_connect");
+  DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
 #else
   int flags, res, s_err;
+  DBUG_ENTER("my_connect");
+  DBUG_PRINT("enter", ("fd: %d  timeout: %u", fd, timeout));
 
   /*
     If they passed us a timeout of zero, we should behave
@@ -157,24 +160,26 @@ int my_connect(my_socket fd, const struc
   */
 
   if (timeout == 0)
-    return connect(fd, (struct sockaddr*) name, namelen);
+    DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
 
   flags = fcntl(fd, F_GETFL, 0);	  /* Set socket to not block */
 #ifdef O_NONBLOCK
   fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
 #endif
 
+  DBUG_PRINT("info", ("connecting non-blocking"));
   res= connect(fd, (struct sockaddr*) name, namelen);
+  DBUG_PRINT("info", ("connect result: %d  errno: %d", res, errno));
   s_err= errno;			/* Save the error... */
   fcntl(fd, F_SETFL, flags);
   if ((res != 0) && (s_err != EINPROGRESS))
   {
     errno= s_err;			/* Restore it */
-    return(-1);
+    DBUG_RETURN(-1);
   }
   if (res == 0)				/* Connected quickly! */
-    return(0);
-  return wait_for_data(fd, timeout);
+    DBUG_RETURN(0);
+  DBUG_RETURN(wait_for_data(fd, timeout));
 #endif
 }
 
@@ -193,26 +198,58 @@ static int wait_for_data(my_socket fd, u
 #ifdef HAVE_POLL
   struct pollfd ufds;
   int res;
+  DBUG_ENTER("wait_for_data");
 
+  DBUG_PRINT("info", ("polling"));
   ufds.fd= fd;
   ufds.events= POLLIN | POLLPRI;
   if (!(res= poll(&ufds, 1, (int) timeout*1000)))
   {
+    DBUG_PRINT("info", ("poll timed out"));
     errno= EINTR;
-    return -1;
+    DBUG_RETURN(-1);
   }
+  DBUG_PRINT("info",
+             ("poll result: %d  errno: %d  revents: 0x%02d  events: 0x%02d",
+              res, errno, ufds.revents, ufds.events));
   if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
-    return -1;
-  return 0;
+    DBUG_RETURN(-1);
+  /*

+    At this point, we know that something happened on the socket.
+    But this does not means that everything is alright.
+    The connect might have failed. We need to retrieve the error code
+    from the socket layer. We must return success only if we are sure
+    that it was really a success. Otherwise we might prevent the caller
+    from trying another address to connect to.
+  */
+  {
+    int         s_err;
+    socklen_t   s_len= sizeof(s_err);
+
+    DBUG_PRINT("info", ("Get SO_ERROR from non-blocked connected socket."));
+    res= getsockopt(fd, SOL_SOCKET, SO_ERROR, &s_err, &s_len);
+    DBUG_PRINT("info", ("getsockopt res: %d  s_err: %d", res, s_err));
+    if (res)
+      DBUG_RETURN(res);
+    /* getsockopt() was successful, check the retrieved status value. */
+    if (s_err)
+    {
+      errno= s_err;
+      DBUG_RETURN(-1);
+    }
+    /* Status from connect() is zero. Socket is successfully connected. */
+  }
+  DBUG_RETURN(0);
 #else
   SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
   fd_set sfds;
   struct timeval tv;
   time_t start_time, now_time;
   int res, s_err;
+  DBUG_ENTER("wait_for_data");
 
   if (fd >= FD_SETSIZE)				/* Check if wrong error */
-    return 0;					/* Can't use timeout */
+    DBUG_RETURN(0);					/* Can't use timeout */
 
   /*
     Our connection is "in progress."  We can use the select() call to wait
@@ -252,11 +289,11 @@ static int wait_for_data(my_socket fd, u
       break;
 #endif
     if (res == 0)					/* timeout */
-      return -1;
+      DBUG_RETURN(-1);
     now_time= my_time(0);
     timeout-= (uint) (now_time - start_time);
     if (errno != EINTR || (int) timeout <= 0)
-      return -1;
+      DBUG_RETURN(-1);
   }
 
   /*
@@ -267,14 +304,14 @@ static int wait_for_data(my_socket fd, u
 
   s_err=0;
   if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
-    return(-1);
+    DBUG_RETURN(-1);
 
   if (s_err)
   {						/* getsockopt could succeed */
     errno = s_err;
-    return(-1);					/* but return an error... */
+    DBUG_RETURN(-1);					/* but return an error... */
   }
-  return (0);					/* ok */
+  DBUG_RETURN(0);					/* ok */
 #endif /* HAVE_POLL */
 }
 #endif /* defined(__WIN__) || defined(__NETWARE__) */
@@ -1877,7 +1914,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
   init_sigpipe_variables
   DBUG_ENTER("mysql_real_connect");
 
-  DBUG_PRINT("enter",("host: %s  db: %s  user: %s",
+  DBUG_PRINT("enter",("host: %s  db: %s  user: %s (client)",
 		      host ? host : "(Null)",
 		      db ? db : "(Null)",
 		      user ? user : "(Null)"));
@@ -1927,6 +1964,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
     unix_socket=mysql->options.unix_socket;
 
   mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
+  DBUG_PRINT("info", ("Connecting"));
 
   /*
     Part 0: Grab a socket and connect it to the server
@@ -1936,6 +1974,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
        mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) &&
       (!host || !strcmp(host,LOCAL_HOST)))
   {
+    DBUG_PRINT("info", ("Using shared memory"));
     if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
 	INVALID_HANDLE_VALUE)
     {
@@ -2034,6 +2073,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
     }
   }
 #endif
+  DBUG_PRINT("info", ("net->vio: %p  protocol: %d",
+                      net->vio, mysql->options.protocol));
   if (!net->vio &&
       (!mysql->options.protocol ||
        mysql->options.protocol == MYSQL_PROTOCOL_TCP))
@@ -2267,6 +2308,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
   /*
     Part 1: Connection established, read and parse first packet
   */
+  DBUG_PRINT("info", ("Read first packet."));
 
   if ((pkt_length=cli_safe_read(mysql)) == packet_error)
   {

Attachment: [text/bzr-bundle] bzr/magnus.blaudd@sun.com-20100415113810-ip02wyearttno7pc.bundle
Thread
bzr commit into mysql-5.1-telco-7.0 branch (magnus.blaudd:3498)Bug#37267 Bug#44344Magnus Blåudd15 Apr