CAMEL-23194: Fix JMS shutdown deadlock that hangs CI builds#22381
Open
CAMEL-23194: Fix JMS shutdown deadlock that hangs CI builds#22381
Conversation
Root cause: deadlock between BaseService.lock and Spring's
lifecycleMonitor during CamelContext shutdown in afterAll.
Thread 1 (afterAll -> context.stop()):
AbstractCamelContext.doStop()
-> JmsProducer.doStop()
-> ReplyManagerSupport.doStop()
-> DefaultMessageListenerContainer.doShutdown()
-> Object.wait() <- blocked, waiting for listener thread
Thread 2 (QueueReplyManager listener):
DestinationResolverDelegate.resolveDestinationName()
-> BaseService.lock <- blocked, held by Thread 1
Introduced by CAMEL-20199 (Oct 2024) which migrated synchronized
blocks to ReentrantLock. Before: BaseService.stop() used
synchronized(lock) on a private Object, while the inner class used
synchronized(QueueReplyManager.this) on the instance monitor — two
independent locks. After: both became QueueReplyManager.this.lock
(the same inherited ReentrantLock), creating the circular wait.
Fix: DestinationResolverDelegate now uses a dedicated ReentrantLock
instead of BaseService.lock, restoring the original two-lock design.
Added volatile + fast-path for the destination field.
Applied to both camel-jms and camel-sjms which share the same
pattern via their respective QueueReplyManager classes.
10d55fb to
ec06502
Compare
gnodet
approved these changes
Apr 1, 2026
Contributor
|
🧪 CI tested the following changed modules:
All tested modules (84 modules)
|
Contributor
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
oscerd
approved these changes
Apr 2, 2026
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
Claude Code on behalf of Federico Mariani
Fixes the JMS test deadlock that has been hanging CI builds, causing repeated ABORTs on camel-4.14.x and camel-4.18.x.
Root Cause
CAMEL-20199 (Jul/Oct 2024) migrated
synchronizedblocks toReentrantLockfor virtual thread support. This accidentally collapsed two independent locks into one:BaseService.stop()usedsynchronized(lock)(a privateObject), whileDestinationResolverDelegateusedsynchronized(QueueReplyManager.this)(the instance monitor) — two independent locks, no deadlock possible.QueueReplyManager.this.lock.lock()— the sameReentrantLockinherited fromBaseService, creating a circular wait during shutdown.Deadlock Sequence
Fix
DestinationResolverDelegatenow uses a dedicatedReentrantLockinstead ofBaseService.lock, restoring the original two-lock designvolatile+ fast-path check on thedestinationfieldcamel-jmsandcamel-sjms(identical pattern)junit.jupiter.execution.timeout.default = 10mfor camel-jms tests as extra safetyTest plan
for i in $(seq 1 50); do mvn test -pl components/camel-jms -Dtest="JmsHttpJmsTest,AsyncJmsInOutTest,AsyncJmsProducerTest,JmsInOutPipelineWithBeanTest,JmsInOutRoutingSlipTest,AsyncConsumerInOutTest" -Dsurefire.rerunFailingTestsCount=0 -Dcamel.surefire.forkTimeout=120 -q || echo "FAILED on run $i"; done🤖 Generated with Claude Code