Commit 832a6acb authored by Marko Mäkelä's avatar Marko Mäkelä

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@273a93396f49c7e0a8b07b260128d9a990c2b154
parent d1af93a5
......@@ -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 */
......
/*****************************************************************************
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;
}
}
}
......
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