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@273a93396f
This commit is contained in:
parent
d1af93a5e8
commit
832a6acb72
@ -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 @@ public:
|
||||
}
|
||||
|
||||
/** 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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user