Commit 575c7b37 authored by Dmitry Lenev's avatar Dmitry Lenev

Fix for sporadical crashes of lock_multi_bug38499.test

caused by patch which implemented new type-of-operation-aware
metadata locks and added a wait-for graph based deadlock
detector to the MDL subsystem (this patch fixed bug #46272
"MySQL 5.4.4, new MDL: unnecessary deadlock" and bug #37346
"innodb does not detect deadlock between update and alter
table").

Crashes were caused by a race in MDL_context::try_acquire_lock().
This method added MDL_ticket to the list of granted tickets and
released lock protecting list before setting MDL_ticket::m_lock.
Thus some other thread was able to see ticket without properly
set m_lock member for some short period of time. If this thread
called method involving this member during this period crash
happened.

This fix ensures that MDL_ticket::m_lock is set in all cases
when ticket is added to granted/pending lists in MDL_lock.

sql/mdl.cc:
  We must set MDL_ticket::m_lock member before adding ticket
  to the list of granted tickets, since such tickets can be
  accessed by other threads which might call methods using
  this member.
  Added assert which ensures that all MDL_tickets which are
  added to the granted/pending lists have properly set
  MDL_ticket::m_lock member.
sql/mdl.h:
  Adjusted comment describing MDL_ticket::m_lock member to
  reflect current reality.
  Added accessor method for this member.
parent 6d9a7ada
...@@ -838,6 +838,12 @@ void MDL_lock::Ticket_list::clear_bit_if_not_in_list(enum_mdl_type type) ...@@ -838,6 +838,12 @@ void MDL_lock::Ticket_list::clear_bit_if_not_in_list(enum_mdl_type type)
void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
{ {
/*
Ticket being added to the list must have MDL_ticket::m_lock set,
since for such tickets methods accessing this member might be
called by other threads.
*/
DBUG_ASSERT(ticket->get_lock());
m_list.push_front(ticket); m_list.push_front(ticket);
m_bitmap|= MDL_BIT(ticket->get_type()); m_bitmap|= MDL_BIT(ticket->get_type());
} }
...@@ -1317,11 +1323,10 @@ MDL_context::try_acquire_lock(MDL_request *mdl_request) ...@@ -1317,11 +1323,10 @@ MDL_context::try_acquire_lock(MDL_request *mdl_request)
if (lock->can_grant_lock(mdl_request->type, this)) if (lock->can_grant_lock(mdl_request->type, this))
{ {
ticket->m_lock= lock;
lock->m_granted.add_ticket(ticket); lock->m_granted.add_ticket(ticket);
rw_unlock(&lock->m_rwlock); rw_unlock(&lock->m_rwlock);
ticket->m_lock= lock;
m_tickets.push_front(ticket); m_tickets.push_front(ticket);
mdl_request->ticket= ticket; mdl_request->ticket= ticket;
......
...@@ -397,6 +397,7 @@ class MDL_ticket ...@@ -397,6 +397,7 @@ class MDL_ticket
m_type == MDL_EXCLUSIVE; m_type == MDL_EXCLUSIVE;
} }
enum_mdl_type get_type() const { return m_type; } enum_mdl_type get_type() const { return m_type; }
MDL_lock *get_lock() const { return m_lock; }
void downgrade_exclusive_lock(enum_mdl_type type); void downgrade_exclusive_lock(enum_mdl_type type);
bool has_stronger_or_equal_type(enum_mdl_type type) const; bool has_stronger_or_equal_type(enum_mdl_type type) const;
...@@ -423,7 +424,9 @@ class MDL_ticket ...@@ -423,7 +424,9 @@ class MDL_ticket
*/ */
MDL_context *m_ctx; MDL_context *m_ctx;
/** Pointer to the lock object for this lock ticket. Context private. */ /**
Pointer to the lock object for this lock ticket. Externally accessible.
*/
MDL_lock *m_lock; MDL_lock *m_lock;
private: private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment