MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Ramil Kalimullin Date:November 20 2008 11:25am
Subject:bzr commit into mysql-5.1 branch (ramil:2721) Bug#40770
View as plain text  
#At file:///home/ram/mysql/b40770.5.1-bugteam/

 2721 Ramil Kalimullin	2008-11-20
      Fix for bug#40770: Server Crash when running with triggers including
      variable settings (rpl_sys)
      
      Problem: under certain conditions (e.g. user variables usage in triggers)
      accessing a user defined variable we may use a variables hash table that
      belongs to already deleted thread. It happens if
      thd= new THD;
      has the same address as just deleted thd as we use
      if (stored_thd == thd)
      to check.
      That may lead to unpredictable results, server crash etc.
      
      Fix: use thread_id instead of thd address to distinguish threads.
      
      Note: no simple and repeatable test case.
modified:
  sql/item_func.cc
  sql/item_func.h

per-file messages:
  sql/item_func.cc
    Fix for bug#40770: Server Crash when running with triggers including
    variable settings (rpl_sys)
      - store and use thd->thread_id to distinguish threads instead of
    thread address as it may be the same as just deleted thread had, 
    i.e. we may get (old_thd == new_thd) after
    delete old_thd;
    new_thd= new THD;
      - set entry_thread_id only when we get a real entry, clear it 
    if the hash search fails.
  sql/item_func.h
    Fix for bug#40770: Server Crash when running with triggers including
    variable settings (rpl_sys)
      - Item_func_set_user_var::entry_thread_id introduced.
=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2008-11-18 11:38:28 +0000
+++ b/sql/item_func.cc	2008-11-20 11:25:26 +0000
@@ -3810,11 +3810,14 @@ static user_var_entry *get_variable(HASH
 
 bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
 {
-  if (thd == entry_thd && entry)
+  if (entry && thd->thread_id == entry_thread_id)
     goto end; // update entry->update_query_id for PS
-  entry_thd= thd;
   if (!(entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
+  {
+    entry_thread_id= 0;
     return TRUE;
+  }
+  entry_thread_id= thd->thread_id;
   /* 
      Remember the last query which updated it, this way a query can later know
      if this variable is a constant item in the query (it is if update_query_id

=== modified file 'sql/item_func.h'
--- a/sql/item_func.h	2008-10-09 15:03:23 +0000
+++ b/sql/item_func.h	2008-11-20 11:25:26 +0000
@@ -1295,16 +1295,16 @@ class Item_func_set_user_var :public Ite
   enum Item_result cached_result_type;
   user_var_entry *entry;
   /*
-    The entry_thd variable is used:
+    The entry_thread_id variable is used:
     1) to skip unnecessary updates of the entry field (see above);
     2) to reset the entry field that was initialized in the other thread
        (for example, an item tree of a trigger that updates user variables
-       may be shared between several connections, and the entry_thd field
+       may be shared between several connections, and the entry_thread_id field
        prevents updates of one connection user variables from a concurrent
        connection calling the same trigger that initially updated some
        user variable it the first connection context).
   */
-  THD *entry_thd;
+  my_thread_id entry_thread_id;
   char buffer[MAX_FIELD_WIDTH];
   String value;
   my_decimal decimal_buff;
@@ -1321,7 +1321,7 @@ public:
   LEX_STRING name; // keep it public
   Item_func_set_user_var(LEX_STRING a,Item *b)
     :Item_func(b), cached_result_type(INT_RESULT),
-     entry(NULL), entry_thd(NULL), name(a)
+     entry(NULL), entry_thread_id(0), name(a)
   {}
   enum Functype functype() const { return SUSERVAR_FUNC; }
   double val_real();

Thread
bzr commit into mysql-5.1 branch (ramil:2721) Bug#40770Ramil Kalimullin20 Nov