Skip to content
Permalink
Browse files
MDEV-23996 Race conditions in SHOW ENGINE INNODB MUTEX
The function innodb_show_mutex_status() is the only ultimate caller of
LatchCounter::iterate() via MutexMonitor::iterate(). Because the call
is not protected by LatchCounter::m_mutex, any mutex_create() or
mutex_free() that is invoked concurrently during the execution, bad
things such as a crash could happen.

The most likely way for this to happen is buffer pool resizing,
which could cause buf_block_t::mutex (which existed before MDEV-15053)
to be created or freed. We could also register InnoDB mutexes in
TrxFactory::init() if trx_pools needs to grow.

The view INFORMATION_SCHEMA.INNODB_MUTEXES is not affected, because it
only displays information about rw-locks, not mutexes.

This commit intentionally touches also MutexMonitor::iterate()
and the only code that interfaces with LatchCounter::iterate()
to make it clearer for future readers that the scattered code
that is obfuscated by templates belongs together.

This is based on
mysql/mysql-server@273a933
  • Loading branch information
dr-m committed Oct 20, 2020
1 parent d1af93a commit 832a6ac
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 23 deletions.
@@ -16332,8 +16332,7 @@ struct ShowStatus {
/** Collect the latch metrics. Ignore entries where the
spins and waits are zero.
@param[in] count The latch metrics */
void operator()(Count* count)
UNIV_NOTHROW
void operator()(Count* count) const UNIV_NOTHROW
{
if (count->m_spins > 0 || count->m_waits > 0) {

@@ -16361,13 +16360,8 @@ struct ShowStatus {
bool operator()(latch_meta_t& latch_meta)
UNIV_NOTHROW
{
latch_meta_t::CounterType* counter;

counter = latch_meta.get_counter();

GetCount get_count(latch_meta.get_name(), &m_values);

counter->iterate(get_count);
latch_meta.get_counter()->iterate(
GetCount(latch_meta.get_name(), &m_values));

return(true);
}
@@ -659,10 +659,10 @@ class LatchCounter {
}

/** Iterate over the counters */
template <typename Callback>
void iterate(Callback& callback) const
UNIV_NOTHROW
template<typename C> void iterate(const C& callback) UNIV_NOTHROW
{
m_mutex.enter();

Counters::const_iterator end = m_counters.end();

for (Counters::const_iterator it = m_counters.begin();
@@ -671,6 +671,8 @@ class LatchCounter {

callback(*it);
}

m_mutex.exit();
}

/** Disable the monitoring */
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -142,16 +142,10 @@ class MutexMonitor {

/* Some of the slots will be null in non-debug mode */

if (*it == NULL) {
continue;
}

latch_meta_t* latch_meta = *it;

bool ret = callback(*latch_meta);

if (!ret) {
return(ret);
if (latch_meta_t* l= *it) {
if (!callback(*l)) {
return false;
}
}
}

0 comments on commit 832a6ac

Please sign in to comment.