List:Commits« Previous MessageNext Message »
From:Tatiana A. Nurnberg Date:June 15 2008 3:37pm
Subject:bzr commit into mysql-5.1 branch (azundris:2662) Bug#23921
View as plain text  
#At file:///misc/mysql/forest/23921/51-23921/

 2662 Tatiana A. Nurnberg	2008-06-15
      Bug#23921: random failure of user_limits.test
      
      mysqltest disconnect/connect-combo could be so
      quick that connect would hit the server before
      it had processed the disconnect. Since that
      resulted in one more concurrent connection than
      we meant to have, global or per-user
      max-user-connections could be exceeded.
      This could lead to "random" failures in tests
      that set those limits.
modified:
  client/mysqltest.c
  mysql-test/t/disabled.def

per-file messages:
  client/mysqltest.c
    Retry max-connect-retries times if connect in
    connect_n_handle_errors() unexpectedly fails
    on connection-limit as this could be a race.
  mysql-test/t/disabled.def
    enable user_limits
=== modified file 'client/mysqltest.c'
--- a/client/mysqltest.c	2008-05-06 13:37:36 +0000
+++ b/client/mysqltest.c	2008-06-15 15:37:17 +0000
@@ -163,6 +163,8 @@ static ulonglong timer_now(void);
 
 static ulonglong progress_start= 0;
 
+static ulong connection_retry_sleep= 100000; /* Microseconds */
+
 /* Precompiled re's */
 static my_regex_t ps_re;     /* the query can be run using PS protocol */
 static my_regex_t sp_re;     /* the query can be run as a SP */
@@ -4157,7 +4159,6 @@ void safe_connect(MYSQL* mysql, const ch
                   int port, const char *sock)
 {
   int failed_attempts= 0;
-  static ulong connection_retry_sleep= 100000; /* Microseconds */
 
   DBUG_ENTER("safe_connect");
   while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
@@ -4224,6 +4225,7 @@ int connect_n_handle_errors(struct st_co
                             const char* db, int port, const char* sock)
 {
   DYNAMIC_STRING *ds;
+  int failed_attempts= 0;
 
   ds= &ds_res;
 
@@ -4252,9 +4254,43 @@ int connect_n_handle_errors(struct st_co
     dynstr_append_mem(ds, delimiter, delimiter_length);
     dynstr_append_mem(ds, "\n", 1);
   }
-  if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
+  while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
                           CLIENT_MULTI_STATEMENTS))
   {
+    /*
+      If we have used up all our connections check whether this
+      is expected (by --error). If so, handle the error right away.
+      Otherwise, give it some extra time to rule out race-conditions.
+      If extra-time doesn't help, we have an unexpected error and
+      must abort -- just proceeding to handle_error() when second
+      and third chances are used up will handle that for us.
+
+      There are various user-limits of which only max_user_connections
+      and max_connections_per_hour apply at connect time. For the
+      the second to create a race in our logic, we'd need a limits
+      test that runs without a FLUSH for longer than an hour, so we'll
+      stay clear of trying to work out which exact user-limit was
+      exceeded.
+    */
+
+    if (((mysql_errno(con) == ER_TOO_MANY_USER_CONNECTIONS) ||
+         (mysql_errno(con) == ER_USER_LIMIT_REACHED)) &&
+        (failed_attempts++ < opt_max_connect_retries))
+    {
+      uint i;
+      for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
+        if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
+             (command->expected_errors.err[i].code.errnum == mysql_errno(con))) ||
+            ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
+             (strncmp(command->expected_errors.err[i].code.sqlstate,
+                      mysql_sqlstate(con), SQLSTATE_LENGTH) == 0)))
+          goto do_handle_error;                 /* expected error, handle */
+
+      my_sleep(connection_retry_sleep);         /* unexpected error, wait */
+      continue;                                 /* and give it 1 more chance */
+    }
+
+do_handle_error:
     var_set_errno(mysql_errno(con));
     handle_error(command, mysql_errno(con), mysql_error(con),
 		 mysql_sqlstate(con), ds);

=== modified file 'mysql-test/t/disabled.def'
--- a/mysql-test/t/disabled.def	2008-05-23 16:42:54 +0000
+++ b/mysql-test/t/disabled.def	2008-06-15 15:37:17 +0000
@@ -11,7 +11,6 @@
 ##############################################################################
 federated_transactions   : Bug#29523 Transactions do not work
 csv_alter_table      : Bug#33696 2008-01-21 pcrews no .result file - bug allows NULL columns in CSV tables
-user_limits     : Bug#23921 random failure of user_limits.test
 thread_cache_size_func : Bug#36733 main.thread_cache_size_func fails randomly
 binlog_cache_size_basic_32            : Bug #36522: Some tests of system variables have diffs on 64bit platorms
 bulk_insert_buffer_size_basic_32      : Bug #36522: Some tests of system variables have diffs on 64bit platorms

Thread
bzr commit into mysql-5.1 branch (azundris:2662) Bug#23921Tatiana A. Nurnberg15 Jun