[Bug] Thread leak in NacosRegistry.scheduleServiceNamesLookup due to race condition
#15886 opened on Dec 20, 2025
Description
Pre-check
- I am sure that all the content I provide is in English.
Search before asking
- I had searched in the issues and found no similar issues.
Apache Dubbo Component
Java SDK (apache/dubbo)
Dubbo Version
Dubbo 3.3.x (Confirmed in latest master branch) & Dubbo 2.7.x. JDK 1.8+, All Operating Systems.
Steps to reproduce this issue
- This issue is identified via static code analysis (concurrency safety check).
- It is located in
org.apache.dubbo.registry.nacos.NacosRegistrymethodscheduleServiceNamesLookup. - The method uses a "Check-Then-Act" pattern to lazily initialize the
scheduledExecutorService. - Although the field is
volatile, the initialization block is NOT synchronized.
Code Analysis:
When scheduleServiceNamesLookup is called concurrently (e.g. via admin protocol), a race condition occurs:
if (scheduledExecutorService == null) { // Thread A and B can pass here simultaneously
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); // Executed twice
// ...
}
What you expected to happen
The scheduledExecutorService should be initialized as a Singleton in a thread-safe manner (e.g., using Double-Checked Locking). Only one thread pool should be created to avoid thread leaks.
Anything else
Proposed Solution (Double-Checked Locking)
I suggest modifying the code to use synchronized DCL:
private void scheduleServiceNamesLookup(final URL url, final NacosAggregateListener listener) { if (scheduledExecutorService == null) { synchronized (this) { if (scheduledExecutorService == null) { // Recommend naming the thread for better debuggability scheduledExecutorService = Executors.newSingleThreadScheduledExecutor( new NamedThreadFactory("Dubbo-Nacos-Registry-Scheduler", true) ); scheduledExecutorService.scheduleAtFixedRate( () -> { // ... existing logic ... }, LOOKUP_INTERVAL, LOOKUP_INTERVAL, TimeUnit.SECONDS); } } } }
Are you willing to submit a pull request to fix on your own?
- Yes I am willing to submit a pull request on my own!
Code of Conduct
- I agree to follow this project's Code of Conduct