List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:August 31 2007 2:00am
Subject:bk commit into 5.0 tree (davi:1.2510) BUG#28870
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of davi. When davi does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-08-30 23:00:33-03:00, davi@stripped +1 -0
  Bug#28870 check that table locks are released/reset
  
  The problem is that some mysql_lock_tables error paths are not resetting the
  tables lock type back to TL_UNLOCK. If the lock types are not reset properly,
  a table might be returned to the table cache with wrong lock_type.
  
  The proposed fix is to ensure that the tables lock type is always properly
  reset when mysql_lock_tables fails.

  sql/lock.cc@stripped, 2007-08-30 23:00:29-03:00, davi@stripped +30 -24
    Move mysql_lock_tables cleanup sequence to a separate function and take
    steps to ensure it is always called for each error exit path.

diff -Nrup a/sql/lock.cc b/sql/lock.cc
--- a/sql/lock.cc	2007-08-27 10:13:52 -03:00
+++ b/sql/lock.cc	2007-08-30 23:00:29 -03:00
@@ -83,6 +83,22 @@ static int unlock_external(THD *thd, TAB
 static void print_lock_error(int error, const char *);
 
 /*
+  Helper function for mysql_lock_tables error path cleanup
+
+  @param thd The current thread.
+  @param sql_lock Lock structures to reset.
+*/
+static inline void mysql_lock_reset_and_free(THD *thd, MYSQL_LOCK *&sql_lock)
+{
+  if (thd->locked && sql_lock->table_count)
+    VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
+  /* Clear the lock type of all lock data to avoid reusage. */
+  reset_lock_data(sql_lock);
+  my_free((gptr) sql_lock,MYF(0));
+  sql_lock=0;
+}
+
+/*
   Lock tables.
 
   SYNOPSIS
@@ -135,17 +151,12 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
       */
       if (wait_if_global_read_lock(thd, 1, 1))
       {
-        /* Clear the lock type of all lock data to avoid reusage. */
-        reset_lock_data(sql_lock);
-	my_free((gptr) sql_lock,MYF(0));
-	sql_lock=0;
+        mysql_lock_reset_and_free(thd, sql_lock);
 	break;
       }
       if (thd->version != refresh_version)
       {
-        /* Clear the lock type of all lock data to avoid reusage. */
-        reset_lock_data(sql_lock);
-	my_free((gptr) sql_lock,MYF(0));
+        mysql_lock_reset_and_free(thd, sql_lock);
 	goto retry;
       }
     }
@@ -154,10 +165,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
     if (sql_lock->table_count && lock_external(thd, sql_lock->table,
                                                sql_lock->table_count))
     {
-      /* Clear the lock type of all lock data to avoid reusage. */
-      reset_lock_data(sql_lock);
-      my_free((gptr) sql_lock,MYF(0));
-      sql_lock=0;
+      mysql_lock_reset_and_free(thd, sql_lock);
       break;
     }
     thd->proc_info="Table lock";
@@ -172,22 +180,12 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
                                                      thd->lock_id)];
     if (rc > 1)                                 /* a timeout or a deadlock */
     {
-      if (sql_lock->table_count)
-        VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
+      mysql_lock_reset_and_free(thd, sql_lock);
       my_error(rc, MYF(0));
-      my_free((gptr) sql_lock,MYF(0));
-      sql_lock= 0;
       break;
     }
     else if (rc == 1)                           /* aborted */
     {
-      /*
-        reset_lock_data is required here. If thr_multi_lock fails it
-        resets lock type for tables, which were locked before (and
-        including) one that caused error. Lock type for other tables
-        preserved.
-      */
-      reset_lock_data(sql_lock);
       thd->some_tables_deleted=1;		// Try again
       sql_lock->lock_count= 0;                  // Locks are already freed
     }
@@ -205,9 +203,17 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
     }
     thd->proc_info=0;
 
+    if (sql_lock->lock_count)
+        thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
+
+    /*
+      If thr_multi_lock fails it resets lock type for tables, which
+      were locked before (and including) one that caused error. Lock
+      type for other tables preserved.
+    */
+    mysql_lock_reset_and_free(thd, sql_lock);
+
     /* some table was altered or deleted. reopen tables marked deleted */
-    mysql_unlock_tables(thd,sql_lock);
-    thd->locked=0;
 retry:
     sql_lock=0;
     if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
Thread
bk commit into 5.0 tree (davi:1.2510) BUG#28870Davi Arnaut31 Aug
  • Re: bk commit into 5.0 tree (davi:1.2510) BUG#28870Konstantin Osipov7 Sep