diff options
author | Dmitry Lenev <dlenev@mysql.com> | 2010-02-01 17:38:50 +0300 |
---|---|---|
committer | Dmitry Lenev <dlenev@mysql.com> | 2010-02-01 17:38:50 +0300 |
commit | e89c08b6708f0fffa6b644bed314663baed51a87 (patch) | |
tree | 8c0d1f8b9001bcae13ffa9c561d24933dd2f21ce /sql | |
parent | 83d538493117fde9821bdf0aaf546edcb7fe5188 (diff) | |
download | mariadb-git-e89c08b6708f0fffa6b644bed314663baed51a87.tar.gz |
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.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/mdl.cc | 9 | ||||
-rw-r--r-- | sql/mdl.h | 5 |
2 files changed, 11 insertions, 3 deletions
diff --git a/sql/mdl.cc b/sql/mdl.cc index 1990ce2800b..fe9f4053e67 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -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) { + /* + 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_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)) { + ticket->m_lock= lock; lock->m_granted.add_ticket(ticket); rw_unlock(&lock->m_rwlock); - ticket->m_lock= lock; - m_tickets.push_front(ticket); mdl_request->ticket= ticket; diff --git a/sql/mdl.h b/sql/mdl.h index 848c446496f..d560f38ce0a 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -397,6 +397,7 @@ public: m_type == MDL_EXCLUSIVE; } 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); bool has_stronger_or_equal_type(enum_mdl_type type) const; @@ -423,7 +424,9 @@ private: */ 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; private: |