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 { ...@@ -16332,8 +16332,7 @@ struct ShowStatus {
/** Collect the latch metrics. Ignore entries where the /** Collect the latch metrics. Ignore entries where the
spins and waits are zero. spins and waits are zero.
@param[in] count The latch metrics */ @param[in] count The latch metrics */
void operator()(Count* count) void operator()(Count* count) const UNIV_NOTHROW
UNIV_NOTHROW
{ {
if (count->m_spins > 0 || count->m_waits > 0) { if (count->m_spins > 0 || count->m_waits > 0) {
...@@ -16361,13 +16360,8 @@ struct ShowStatus { ...@@ -16361,13 +16360,8 @@ struct ShowStatus {
bool operator()(latch_meta_t& latch_meta) bool operator()(latch_meta_t& latch_meta)
UNIV_NOTHROW UNIV_NOTHROW
{ {
latch_meta_t::CounterType* counter; latch_meta.get_counter()->iterate(
GetCount(latch_meta.get_name(), &m_values));
counter = latch_meta.get_counter();
GetCount get_count(latch_meta.get_name(), &m_values);
counter->iterate(get_count);
return(true); return(true);
} }
......
...@@ -659,10 +659,10 @@ class LatchCounter { ...@@ -659,10 +659,10 @@ class LatchCounter {
} }
/** Iterate over the counters */ /** Iterate over the counters */
template <typename Callback> template<typename C> void iterate(const C& callback) UNIV_NOTHROW
void iterate(Callback& callback) const
UNIV_NOTHROW
{ {
m_mutex.enter();
Counters::const_iterator end = m_counters.end(); Counters::const_iterator end = m_counters.end();
for (Counters::const_iterator it = m_counters.begin(); for (Counters::const_iterator it = m_counters.begin();
...@@ -671,6 +671,8 @@ class LatchCounter { ...@@ -671,6 +671,8 @@ class LatchCounter {
callback(*it); callback(*it);
} }
m_mutex.exit();
} }
/** Disable the monitoring */ /** Disable the monitoring */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -142,16 +142,10 @@ class MutexMonitor { ...@@ -142,16 +142,10 @@ class MutexMonitor {
/* Some of the slots will be null in non-debug mode */ /* Some of the slots will be null in non-debug mode */
if (*it == NULL) { if (latch_meta_t* l= *it) {
continue; if (!callback(*l)) {
return false;
} }
latch_meta_t* latch_meta = *it;
bool ret = callback(*latch_meta);
if (!ret) {
return(ret);
} }
} }
......
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