diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-12-21 11:07:25 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-12-21 11:07:25 +0200 |
commit | 3b33593f80442214640eefb2ce75c34698c8043b (patch) | |
tree | 76c81a12bc2976603812acbcd74cff3c20a5962c | |
parent | 3fd80d08740d3ad2426bfb8eb9debc40d96e2a20 (diff) | |
download | mariadb-git-3b33593f80442214640eefb2ce75c34698c8043b.tar.gz |
MDEV-27332 SIGSEGV in fetch_data_into_cache()
Since commit fb335b48b5e3263698b7d9a74ff3f20ef406df9f we may have
a null pointer in purge_sys.query when fetch_data_into_cache() is
invoked and innodb_force_recovery>4. This is because the call to
purge_sys.create() would be skipped.
fetch_data_into_cache(): Load the purge_sys pseudo transaction pointer
to a local variable (null pointer if purge_sys is not initialized).
-rw-r--r-- | mysql-test/suite/innodb/r/read_only_recover_committed.result | 7 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/read_only_recover_committed.test | 7 | ||||
-rw-r--r-- | storage/innobase/trx/trx0i_s.cc | 4 |
3 files changed, 17 insertions, 1 deletions
diff --git a/mysql-test/suite/innodb/r/read_only_recover_committed.result b/mysql-test/suite/innodb/r/read_only_recover_committed.result index 278905a976b..0bfba662c15 100644 --- a/mysql-test/suite/innodb/r/read_only_recover_committed.result +++ b/mysql-test/suite/innodb/r/read_only_recover_committed.result @@ -63,6 +63,13 @@ SELECT * FROM t; a 3 20 +# +# MDEV-27332 SIGSEGV in fetch_data_into_cache +# +BEGIN; +SELECT trx_state FROM information_schema.innodb_trx; +trx_state +COMMIT; SELECT * FROM t; a 3 diff --git a/mysql-test/suite/innodb/t/read_only_recover_committed.test b/mysql-test/suite/innodb/t/read_only_recover_committed.test index 9ad09bb9b3a..439f57e9fad 100644 --- a/mysql-test/suite/innodb/t/read_only_recover_committed.test +++ b/mysql-test/suite/innodb/t/read_only_recover_committed.test @@ -78,6 +78,13 @@ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SELECT * FROM t; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT * FROM t; + +--echo # +--echo # MDEV-27332 SIGSEGV in fetch_data_into_cache +--echo # +BEGIN; +SELECT trx_state FROM information_schema.innodb_trx; +COMMIT; --let $restart_parameters= --source include/restart_mysqld.inc SELECT * FROM t; diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index afd644f3c70..951770e5bb7 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -1275,6 +1275,8 @@ static void fetch_data_into_cache_low(trx_i_s_cache_t *cache, const trx_t *trx) static void fetch_data_into_cache(trx_i_s_cache_t *cache) { + const trx_t *const purge_trx= purge_sys.query ? purge_sys.query->trx : NULL; + ut_ad(lock_mutex_own()); trx_i_s_cache_clear(cache); @@ -1284,7 +1286,7 @@ static void fetch_data_into_cache(trx_i_s_cache_t *cache) trx != NULL; trx= UT_LIST_GET_NEXT(trx_list, trx)) { - if (trx->state != TRX_STATE_NOT_STARTED && trx != purge_sys.query->trx) + if (trx != purge_trx && trx->state != TRX_STATE_NOT_STARTED) { mutex_enter(&trx->mutex); if (trx->state != TRX_STATE_NOT_STARTED) |