From db0f8f8f0cda386f6447bf997c8a89b5806e23a2 Mon Sep 17 00:00:00 2001 From: Brian Kassouf Date: Fri, 13 Mar 2020 15:03:58 -0700 Subject: [PATCH] storage/raft: Fix leadership deadlock (#8547) * storage/raft: Fix leadership deadlock * Update comment --- physical/raft/raft.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/physical/raft/raft.go b/physical/raft/raft.go index 3ffb81a9e60..c7d9d6ca96d 100644 --- a/physical/raft/raft.go +++ b/physical/raft/raft.go @@ -999,12 +999,21 @@ type RaftLock struct { func (l *RaftLock) monitorLeadership(stopCh <-chan struct{}, leaderNotifyCh <-chan bool) <-chan struct{} { leaderLost := make(chan struct{}) go func() { - select { - case isLeader := <-leaderNotifyCh: - if !isLeader { - close(leaderLost) + for { + select { + case isLeader := <-leaderNotifyCh: + // leaderNotifyCh may deliver a true value initially if this + // server is already the leader prior to RaftLock.Lock call + // (the true message was already queued). The next message is + // always going to be false. The for loop should loop at most + // twice. + if !isLeader { + close(leaderLost) + return + } + case <-stopCh: + return } - case <-stopCh: } }() return leaderLost