apache / apache/shenyu

[BUG] SingletonExecutor worker threads never shut down (incomplete #6262 fix)

Open
#6,660 2 comments 0 reactions 0 assignees View on GitHub
priority: high type: bug
Dominant language
Java
Stars
8.8k
Forks
3.1k
Avg merge
7d 1h
Merged PRs (30d)
85

Description

- Severity: High
- Location:
`shenyu-disruptor/src/main/java/org/apache/shenyu/disruptor/thread/OrderlyExecutor.java:37,66-77`; `shenyu-disruptor/src/main/java/org/apache/shenyu/disruptor/provider/DisruptorProvider.java:114-121`
-
Description:
In orderly mode `OrderlyExecutor` populates `virtualExecutors` (a `ConcurrentSkipListMap`) with `corePoolSize` `SingletonExecutor` instances, each its own `ThreadPoolExecutor(1,1,…,new LinkedBlockingQueue<>(), threadFactory)`. `DisruptorProvider.shutdown()` only calls `executor.shutdown()` on the outer `OrderlyExecutor`; `OrderlyExecutor` does not override `shutdown()`/`shutdownNow()` to cascade. The worker thread factory is `DisruptorThreadFactory.create("shenyu_disruptor_consumer_", false)` — `daemon=false` (`DisruptorProviderManage.java:110`) — so the leaked workers are non-daemon and keep the JVM alive.
-
Impact:
After `DisruptorProvider.shutdown()` in orderly mode, `corePoolSize` non-daemon threads (default `availableProcessors()*2`) stay alive forever; JVM cannot exit cleanly. Hot-reload/repeated-init leaks threads each cycle.
-
Suggested fix:
Override `shutdown()`/`shutdownNow()` in `OrderlyExecutor` to iterate `virtualExecutors.values()` and shut down each `SingletonExecutor`, then `super.shutdown()`.
-
Confidence: High
- Related existing: #6262 — but the merged fix only added outer `executor.shutdown()`; inner `SingletonExecutor` leak unfixed. Distinct facet.

---
_Identified during the 2026-08-02 deep re-scan; full list in [`docs/scan2-2026-08-02/00-consolidated-critical-high.md`](docs/scan2-2026-08-02/00-consolidated-critical-high.md)._

Contributor guide

No contributing guide indexed for this repository

Research direction

Read OrderlyExecutor.java at the listed fields and executor methods, then inspect DisruptorProvider.shutdown() and DisruptorProviderManage.java:110 to confirm the non-daemon thread factory. Trace how orderly mode populates virtualExecutors and how shutdown currently reaches the outer executor. Done means shutdown and shutdownNow cascade to the SingletonExecutor workers so repeated initialization does not leave non-daemon threads keeping the JVM alive.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.