summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-02-12 14:27:12 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2021-02-12 14:27:12 +0200
commit8afdfd74f0a72c72cf6dc4b35c4648ff65d88355 (patch)
treea13f05182b2899b162ff4298b36b796f64ad5448
parent760a1ca549d26a9e062d1b9cc8c3d4dfadf08ffb (diff)
downloadmariadb-git-bb-10.6-MDEV-20612-4.tar.gz
Amend f98795a8749b8053dca2b742938a8d289c7b515abb-10.6-MDEV-20612-4
We must never release lock_sys.latch while holding any lock_sys_t::hash_latch. Failure to do that could lead to memory corruption if the buffer pool is resized between the time lock_sys.latch is released and the hash_latch is released.
-rw-r--r--storage/innobase/include/lock0lock.h7
-rw-r--r--storage/innobase/lock/lock0lock.cc6
-rw-r--r--storage/innobase/lock/lock0prdt.cc3
3 files changed, 12 insertions, 4 deletions
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index 9607d9b42a7..f81d7c65b84 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -898,7 +898,12 @@ struct LockMutexGuard
struct LockGuard
{
LockGuard(lock_sys_t::hash_table &hash, const page_id_t id);
- ~LockGuard() { lock_sys.rd_unlock(); latch->release(); }
+ ~LockGuard()
+ {
+ latch->release();
+ /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */
+ lock_sys.rd_unlock();
+ }
private:
/** The hash bucket */
lock_sys_t::hash_latch *latch;
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 30ecc913cc5..2e82efe52c9 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -210,8 +210,9 @@ LockGGuard::~LockGGuard()
lock_sys.wr_unlock();
else
{
- lock_sys.rd_unlock();
latch->release();
+ /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */
+ lock_sys.rd_unlock();
}
}
#endif
@@ -233,10 +234,11 @@ LockMultiGuard::LockMultiGuard(lock_sys_t::hash_table &hash,
LockMultiGuard::~LockMultiGuard()
{
- lock_sys.rd_unlock();
latch1->release();
if (latch1 != latch2)
latch2->release();
+ /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */
+ lock_sys.rd_unlock();
}
/** Pretty-print a table lock.
diff --git a/storage/innobase/lock/lock0prdt.cc b/storage/innobase/lock/lock0prdt.cc
index 13f7b092e9d..cb6dde162ce 100644
--- a/storage/innobase/lock/lock0prdt.cc
+++ b/storage/innobase/lock/lock0prdt.cc
@@ -932,6 +932,7 @@ void lock_sys_t::prdt_page_free_from_discard(const page_id_t id, bool all)
lock_rec_discard(rec_hash, lock);
}
- rd_unlock();
latch->release();
+ /* Must be last, to avoid a race with lock_sys_t::hash_table::resize() */
+ rd_unlock();
}