revision-id: 5db4c985188654955350b1417aedb2b6f92774d8 (v5.8-1899-g5db4c9851) parent(s): 73ff40dcbf0a46228ea02d5103d1331335622794 author: Sergei Petrunia committer: Sergei Petrunia timestamp: 2019-11-30 20:03:50 +0300 message: Range Locking, shared locks: fix a bug in acquisition of the same lock twice Check for this case: when the same transaction acquires the same lock twice, the lock should still have m_txnid={the transaction}, m_owners= nullptr. Failure to maintain this invariant breaks the logic in other code and in some scenarios we could end up with shared locks with zero owners. --- utilities/transactions/range_locking/locktree/treenode.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/utilities/transactions/range_locking/locktree/treenode.cc b/utilities/transactions/range_locking/locktree/treenode.cc index 029646d18..725991f7d 100644 --- a/utilities/transactions/range_locking/locktree/treenode.cc +++ b/utilities/transactions/range_locking/locktree/treenode.cc @@ -140,6 +140,9 @@ void treenode::swap_in_place(treenode *node1, treenode *node2) { void treenode::add_shared_owner(TXNID txnid) { assert(m_is_shared); + if (txnid == m_txnid) + return; // acquiring a lock on the same range by the same trx + if (m_txnid != TXNID_SHARED) { m_owners= new TxnidVector; m_owners->insert(m_txnid); @@ -373,7 +376,9 @@ void treenode::recursive_remove(void) { } void treenode::remove_shared_owner(TXNID txnid) { + assert(m_owners->size()>1); m_owners->erase(txnid); + assert(m_owners->size()>0); /* if there is just one owner left, move it to m_txnid */ if (m_owners->size() == 1) {