Release primary lock on election timeout - #196
Open
munakoiso wants to merge 1 commit into
Open
Conversation
munakoiso
force-pushed
the
fix_race_in_failover
branch
from
July 23, 2026 11:33
df10e89 to
68ef9dc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug summary
During a failover election, if the winning replica timed out while waiting for the election manager to release its lock (
epoch_manager), it would throwElectionTimeoutwithout first releasing theleader(PRIMARY_LOCK_PATH) ZooKeeper lock it had already acquired. This left the cluster in a broken state: the "winner" replica held the leader lock in ZK but never actually promoted itself, and no other replica could start a new election because the lock appeared occupied.Root cause
In
_participate_in_election(), after successfully acquiringPRIMARY_LOCK_PATH, the code waits for the manager'sepoch_managerlock to be released (a signal that the manager has finished its cleanup). If this wait times out (because the manager lost its ZK connection and its session had not yet expired),ElectionTimeoutwas raised without releasingPRIMARY_LOCK_PATH:The exception was caught higher up in
_make_election()which logged the error and returnedFalse(no promote). Meanwhile, subsequent calls tomake_election()would immediately bail out on seeing the orphanedleaderlock:The cluster stayed without a primary until the ZK session of the stuck replica eventually expired and the lock was auto-released.
Observed scenario (from faultstorm test logs)
epoch_manager, becomes election manager. Its local PG is also dead, so it votes withlsn=0.lsn=1426231568. Gets elected winner.leaderlock (06:24:50).epoch_managersession lock is still held because the ZK session has not expired yet.election_timeoutwaiting forepoch_managerto become empty expires at 06:24:55.ElectionTimeoutis thrown,leaderlock is not released.Fix
Release
PRIMARY_LOCK_PATHexplicitlyThis allows the next iteration to start a fresh election round without being blocked by an orphaned lock.