ZOOKEEPER-XXXX: Restore interrupt status in quorum catch blocks - #2463
Open
TimurRakhmatullin86 wants to merge 1 commit into
Open
TimurRakhmatullin86 wants to merge 1 commit into
TimurRakhmatullin86 wants to merge 1 commit into
Conversation
Multiple catch(InterruptedException) blocks in the quorum package swallow the interrupt flag without calling Thread.currentThread().interrupt(). This violates the Java interrupt contract: any code higher in the call stack that checks Thread.interrupted() or calls a blocking method will never see the interruption, which can cause threads to hang during shutdown or fail to terminate promptly. This patch adds Thread.currentThread().interrupt() as the first statement in 9 catch blocks across 6 files: - QuorumCnxManager.halt() — after listener.join() - QuorumCnxManager.ListenerHandler.acceptConnections() — after Thread.sleep() in retry loop - QuorumCnxManager.SendWorker.run() — after pollSendQueue() - QuorumPeerMain.runFromConfig() — after quorumPeer.join() - LearnerHandler.shutdown() — after queuedPackets.put() - Observer.waitForReconnectDelayHelper() — after Thread.sleep() - Learner.connectToLeader() — after latch.await() - Learner.connectToLeader() finally — after awaitTermination() - FastLeaderElection.WorkerReceiver.run() — after manager.pollRecvQueue() No behavioral change: each catch block still logs the same message at the same level. The only addition is the single Thread.currentThread().interrupt() call so the flag is preserved for upstream callers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
Summary
Multiple
catch (InterruptedException)blocks in the quorum package swallow the interrupt flag without callingThread.currentThread().interrupt(). This violates the Java interrupt contract: any code higher in the call stack that checksThread.interrupted()or calls a blocking method will never see the interruption, which can cause threads to hang during shutdown or fail to terminate promptly.Changes
This patch adds
Thread.currentThread().interrupt()as the first statement in 9 catch blocks across 6 files:QuorumCnxManager.javahalt()— afterlistener.join()QuorumCnxManager.javaListenerHandler.acceptConnections()— afterThread.sleep()in retry loopQuorumCnxManager.javaSendWorker.run()— afterpollSendQueue()QuorumPeerMain.javarunFromConfig()— afterquorumPeer.join()LearnerHandler.javashutdown()— afterqueuedPackets.put()Observer.javawaitForReconnectDelayHelper()— afterThread.sleep()Learner.javaconnectToLeader()— afterlatch.await()Learner.javaconnectToLeader()finally block — afterawaitTermination()FastLeaderElection.javaWorkerReceiver.run()— aftermanager.pollRecvQueue()Motivation
Per Java best practices (see Java Concurrency in Practice §7.1.3 and the
InterruptedExceptionJavadoc), when a method catchesInterruptedExceptionand does not re-throw it, it must restore the interrupt status by callingThread.currentThread().interrupt(). Without this, the interrupt signal is permanently lost. In ZooKeeper's quorum code, this means:QuorumCnxManager.halt()andSendWorker.run()may not terminate promptly because callers pollingThread.interrupted()never see the flag.FastLeaderElection.WorkerReceiverandLearner.connectToLeader()continue looping after an interrupt without propagating the signal, potentially delaying or preventing clean shutdown.ListenerHandler.acceptConnections()catches the interrupt during a sleep-based retry but never restores the flag, so the retry loop does not respect the shutdown signal from higher-level code.Testing
Thread.currentThread().interrupt()call so the flag is preserved for upstream callers.🤖 Generated with Claude Code