From 1595189250e71d5902fc0f378b0e6b14c5b26901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 6 Oct 2020 22:35:43 +0300 Subject: [PATCH] MDEV-23897 SIGSEGV on commit with innodb_lock_schedule_algorithm=VATS This regression for debug builds was introduced by MDEV-23101 (commit 224c950462a22e09f4e2e37d19218c9129bccba6). Due to MDEV-16664, the parameter innodb_lock_schedule_algorithm=VATS is not enabled by default. The purpose of the added assertions was to enforce the invariant that Galera replication cannot be enabled together with VATS due to MDEV-12837. However, upon closer inspection, it is obvious that the variable 'lock' may be assigned to the null pointer if no match is found in the previous->hash list. lock_grant_and_move_on_page(), lock_grant_and_move_on_rec(): Assert !lock->trx->is_wsrep() only after ensuring that lock is not a null pointer. --- mysql-test/suite/innodb/t/update-cascade.combinations | 5 +++++ storage/innobase/lock/lock0lock.cc | 7 +++---- 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/innodb/t/update-cascade.combinations diff --git a/mysql-test/suite/innodb/t/update-cascade.combinations b/mysql-test/suite/innodb/t/update-cascade.combinations new file mode 100644 index 00000000000..8fb4862675b --- /dev/null +++ b/mysql-test/suite/innodb/t/update-cascade.combinations @@ -0,0 +1,5 @@ +[FCFS] +--innodb-lock-schedule-algorithm=FCFS + +[VATS] +--innodb-lock-schedule-algorithm=VATS diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index e48ac6bcc92..913c80027bf 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -2306,12 +2306,12 @@ lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no) lock = previous->hash; } - ut_ad(!lock->trx->is_wsrep()); ut_ad(previous->hash == lock || previous == lock); /* Grant locks if there are no conflicting locks ahead. Move granted locks to the head of the list. */ while (lock) { /* If the lock is a wait lock on this page, and it does not need to wait. */ + ut_ad(!lock->trx->is_wsrep()); if (lock_get_wait(lock) && lock->un_member.rec_lock.space == space && lock->un_member.rec_lock.page_no == page_no @@ -4211,11 +4211,10 @@ lock_grant_and_move_on_rec( } lock = previous->hash; } - ut_ad(!lock->trx->is_wsrep()); /* Grant locks if there are no conflicting locks ahead. Move granted locks to the head of the list. */ - for (;lock != NULL;) { - + while (lock) { + ut_ad(!lock->trx->is_wsrep()); /* If the lock is a wait lock on this page, and it does not need to wait. */ if (lock->un_member.rec_lock.space == space && lock->un_member.rec_lock.page_no == page_no