Skip to content

Commit

Permalink
Bug#32686116: MYSQL CRASH
Browse files Browse the repository at this point in the history
Problem: Running highly concurrent dump/restore tools could lead to the
server terminating. Root cause was that there was a race condition when
releasing MDLs which could lead invalid memory access.

Specifically, MDL_context::release_lock() executed code that might lead
to deletion of corresponding MDL_lock object first and then called
MDL_ticket_store::remove() method which might have accessed MDL_lock::m_key
key in the deleted object. The former happens really rarely,
when we release the last ticket for this lock, so MDL_lock object
becomes unused, and there are too many unused MDL_lock objects in the system,
and the random search we use to choose objects to release picks up the
specific MDL_lock object. While the latter happens any time when ticket store
contains enough tickets so hash-based ticket map is employed.

Solution: Move the call to MDL_ticket_store::remove() earlier in
MDL_context::relase_lock() so that no access needs to be made to
MDL_lock::key after it can become invalid.

Only manual testing done, as it is very challenging to create a reliable
test case which triggers this rare situation.

Approved by: [email protected]

Change-Id: I87475ffafd4e3f758c5695dbcf9c4e6dff5469b1
  • Loading branch information
Dyre Tjeldvoll authored and Dyre Tjeldvoll committed Apr 29, 2021
1 parent f3130ea commit d0a24b8
Showing 1 changed file with 5 additions and 1 deletion.
6 changes: 5 additions & 1 deletion sql/mdl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4090,6 +4090,11 @@ void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket) {
assert(this == ticket->get_ctx());
mysql_mutex_assert_not_owner(&LOCK_open);

// Remove ticket from the Ticket_store before actually releasing the lock,
// so this removal process can safely reference MDL_lock::m_key in cases
// when Ticket_store uses hash-based secondary index.
m_ticket_store.remove(duration, ticket);

/*
If lock we are about to release requires post-release notification
of SEs, we need to save its MDL_key on stack. This is necessary to
Expand Down Expand Up @@ -4179,7 +4184,6 @@ void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket) {
*/
lock->remove_ticket(this, m_pins, &MDL_lock::m_granted, ticket);
}
m_ticket_store.remove(duration, ticket);
if (ticket->m_hton_notified) {
mysql_mdl_set_status(ticket->m_psi, MDL_ticket::POST_RELEASE_NOTIFY);
m_owner->notify_hton_post_release_exclusive(&key_for_hton);
Expand Down

0 comments on commit d0a24b8

Please sign in to comment.