Commit 0b28a456 authored by Ramil Kalimullin's avatar Ramil Kalimullin
Browse files

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.
parent f7df5c98
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -3810,11 +3810,14 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,

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
+4 −4
Original line number Diff line number Diff line
@@ -1295,16 +1295,16 @@ class Item_func_set_user_var :public Item_func
  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 @@ class Item_func_set_user_var :public Item_func
  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();