From d74f8c8519a6d00dc8b81450c3eadbdef1e0de3e Mon Sep 17 00:00:00 2001 From: Tobias Schottdorf Date: Fri, 5 Apr 2019 13:20:42 +0200 Subject: [PATCH] storage: avoid deadlock due to reentrant RLock Happened to run into this during some unrelated work. Release note: None --- pkg/storage/replica.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/storage/replica.go b/pkg/storage/replica.go index 279a2a650100..6bda6334a0a3 100644 --- a/pkg/storage/replica.go +++ b/pkg/storage/replica.go @@ -864,9 +864,15 @@ func (r *Replica) raftStatusRLocked() *raft.Status { // State returns a copy of the internal state of the Replica, along with some // auxiliary information. func (r *Replica) State() storagepb.RangeInfo { + var ri storagepb.RangeInfo + + // NB: this acquires an RLock(). Reentrant RLocks are deadlock prone, so do + // this first before RLocking below. Performance of this extra lock + // acquisition is not a concern. + ri.ActiveClosedTimestamp = r.maxClosed(context.Background()) + r.mu.RLock() defer r.mu.RUnlock() - var ri storagepb.RangeInfo ri.ReplicaState = *(protoutil.Clone(&r.mu.state)).(*storagepb.ReplicaState) ri.LastIndex = r.mu.lastIndex ri.NumPending = uint64(len(r.mu.proposals)) @@ -893,7 +899,6 @@ func (r *Replica) State() storagepb.RangeInfo { }) } } - ri.ActiveClosedTimestamp = r.maxClosed(context.Background()) return ri }