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.
This commit is contained in:
Dmitry Lenev 2010-02-01 17:38:50 +03:00
parent 83d5384931
commit e89c08b670
2 changed files with 11 additions and 3 deletions

View File

@ -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)
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;

View File

@ -397,6 +397,7 @@ public:
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 @@ private:
*/ */
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: