List:Internals« Previous MessageNext Message »
From:ingo Date:August 31 2005 7:24pm
Subject:bk commit into 4.0 tree (ingo:1.2143) BUG#12845
View as plain text  
Below is the list of changes that have just been committed into a local
4.0 repository of mydev. When mydev 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
  1.2143 05/08/31 19:24:49 ingo@stripped +4 -0
  Bug#12845 - Stress test: Server crashes on  CREATE .. SELECT statement
  Changed definition of open_table(), added 'flags'
  to be able to ignore flush requests. This should be used
  if open_table() runs when there are already locked tables
  in this command. Explicit LOCK TABLE is not affected.
  
  No test case. The bug can only be triggered by true concurrency.
  The stress test suite provides a test case for this.

  sql/sql_table.cc
    1.199 05/08/31 19:24:47 ingo@stripped +19 -2
    Bug#12845 - Stress test: Server crashes on  CREATE .. SELECT statement
    Changed calls to open_table(). Requested to ignore
    flush at places where the command did already lock tables.
    This could happen in CREATE ... SELECT and ALTER TABLE.

  sql/sql_base.cc
    1.192 05/08/31 19:24:47 ingo@stripped +36 -12
    Bug#12845 - Stress test: Server crashes on  CREATE .. SELECT statement
    Changed definition of open_table(), added 'flags'
    to be able to ignore flush requests. This should be used
    if open_table() runs when there are already locked tables
    in this command. Explicit LOCK TABLE is not affected.

  sql/mysql_priv.h
    1.237 05/08/31 19:24:47 ingo@stripped +2 -2
    Bug#12845 - Stress test: Server crashes on  CREATE .. SELECT statement
    Changed declaraction of open_table(), added 'flags'.

  sql/field.h
    1.61 05/08/31 19:24:47 ingo@stripped +2 -2
    Bug#12845 - Stress test: Server crashes on  CREATE .. SELECT statement
    Changed declaraction of open_table(), added 'flags'.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	ingo
# Host:	chilla.local
# Root:	/home/mydev/mysql-4.0-4000

--- 1.60/sql/field.h	2005-03-28 21:36:22 +02:00
+++ 1.61/sql/field.h	2005-08-31 19:24:47 +02:00
@@ -595,8 +595,8 @@
   bool get_time(TIME *ltime);
 
 #if MYSQL_VERSION_ID < 40100
-  friend TABLE *open_table(THD *thd,const char *db,const char *table_name,
-                           const char *alias,bool *refresh);
+  friend TABLE *open_table(THD *thd, const char *db, const char *table_name,
+                           const char *alias, bool *refresh, uint flags);
 #endif
 };
 

--- 1.236/sql/mysql_priv.h	2005-07-26 16:53:32 +02:00
+++ 1.237/sql/mysql_priv.h	2005-08-31 19:24:47 +02:00
@@ -483,8 +483,8 @@
                  ha_rows rows, ulong options);
 int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
 TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
-TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
-		  bool *refresh);
+TABLE *open_table(THD *thd, const char *db, const char *table_name,
+                  const char *alias, bool *refresh, uint flags);
 TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table);
 TABLE *find_locked_table(THD *thd, const char *db,const char *table_name);
 bool reopen_table(TABLE *table,bool locked=0);

--- 1.191/sql/sql_base.cc	2005-07-26 16:53:32 +02:00
+++ 1.192/sql/sql_base.cc	2005-08-31 19:24:47 +02:00
@@ -788,18 +788,35 @@
 }
 
 
-/******************************************************************************
-** open a table
-** Uses a cache of open tables to find a table not in use.
-** If refresh is a NULL pointer, then the is no version number checking and
-** the table is not put in the thread-open-list
-** If the return value is NULL and refresh is set then one must close
-** all tables and retry the open
-******************************************************************************/
+/*
+  Open a table.
+
+  SYNOPSIS
+    open_table()
+    thd             Thread context
+    db              Database name.
+    table_name      Real table name.
+    alias           Table alias.
+    refresh         Pointer to memory that will be set to 1 if
+                    we need to close all tables and reopen them.
+                    If this is a NULL pointer, then there is no version
+                    number checking and the table is not put in the
+                    thread-open-list.
+    flags           Bitmap of flags to modify how open works:
+                    MYSQL_LOCK_IGNORE_FLUSH - Open table even if someone
+                    has done a flush or namelock on it.
 
+  IMPLEMENTATION
+    Uses a cache of open tables to find a table not in use.
 
-TABLE *open_table(THD *thd,const char *db,const char *table_name,
-		  const char *alias,bool *refresh)
+  RETURN
+    NULL        Open failed.  If refresh is set then one should close
+                all other tables and retry the open.
+    #           Success. Pointer to TABLE object for open table.
+*/
+
+TABLE *open_table(THD *thd, const char *db, const char *table_name,
+                  const char *alias, bool *refresh, uint flags)
 {
   reg1	TABLE *table;
   char	key[MAX_DBKEY_LENGTH];
@@ -871,6 +888,13 @@
   {
     if (table->version != refresh_version)
     {
+      if (flags & MYSQL_LOCK_IGNORE_FLUSH)
+      {
+        /* Force close at once after usage */
+        thd->version= table->version;
+        continue;
+      }
+
       /*
       ** There is a refresh in progress for this table
       ** Wait until the table is freed or the thread is killed.
@@ -1470,7 +1494,7 @@
 	!(tables->table=open_table(thd,
 				   tables->db,
 				   tables->real_name,
-				   tables->alias, &refresh)))
+				   tables->alias, &refresh, 0)))
     {
       if (refresh)				// Refresh in progress
       {
@@ -1582,7 +1606,7 @@
   thd->proc_info="Opening table";
   while (!(table=open_table(thd,table_list->db,
 			    table_list->real_name,table_list->alias,
-			    &refresh)) && refresh) ;
+			    &refresh, 0)) && refresh) ;
   if (table)
   {
 #if defined( __WIN__) || defined(OS2)

--- 1.198/sql/sql_table.cc	2005-07-20 21:18:57 +02:00
+++ 1.199/sql/sql_table.cc	2005-08-31 19:24:47 +02:00
@@ -882,11 +882,18 @@
     don't want to delete from it) 2) it would be written before the CREATE
     TABLE, which is a wrong order. So we keep binary logging disabled when we
     open_table().
+
+    When calling this function, one can already have locked tables.
+    If these become refreshed until open_table(), they must not be closed
+    by open_table(). Otherwise the THR_LOCK_DATA would be freed, and at
+    command end, mysql_unlock_tables() might crash. To prevent this, we
+    instruct open_table() to ignore flushes. (Bug #12845)
   */
   tmp_disable_binlog(thd);
   if (!mysql_create_table(thd,db,name,create_info,*extra_fields,*keys,0))
   {
-    if (!(table=open_table(thd,db,name,name,(bool*) 0)))
+    if (! (table= open_table(thd, db, name, name,
+                             (bool*) 0, MYSQL_LOCK_IGNORE_FLUSH)))
       quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
   }
   reenable_binlog(thd);
@@ -1931,7 +1938,17 @@
       DBUG_RETURN(error);
   }
   if (table->tmp_table)
-    new_table=open_table(thd,new_db,tmp_name,tmp_name,0);
+  {
+    /*
+      The old table is still locked. If it becomes refreshed until
+      open_table(), it must not be closed by open_table().
+      Otherwise the THR_LOCK_DATA would be freed, and at command end,
+      mysql_unlock_tables() might crash. To prevent this, we instruct
+      open_table() to ignore flushes. (Bug #12845)
+    */
+    new_table= open_table(thd, new_db, tmp_name, tmp_name,
+                          0, MYSQL_LOCK_IGNORE_FLUSH);
+  }
   else
   {
     char path[FN_REFLEN];
Thread
bk commit into 4.0 tree (ingo:1.2143) BUG#12845ingo31 Aug