Skip to content

HDDS-17254. Prevent client background threads from blocking JVM shutdown - #11667

Merged
smengcl merged 3 commits into
apache:masterfrom
jojochuang:codex/HDDS-17254-client-daemon-threads
Oct 22, 2026
Merged

smengcl merged 3 commits into
apache:masterfrom
jojochuang:codex/HDDS-17254-client-daemon-threads

Conversation

@jojochuang

@jojochuang jojochuang commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Client background executors and timers can keep the JVM alive after the application returns from main if the associated resources remain open. This patch makes the streaming-write response executor, short-circuit connection timer, domain socket factory timer, and default low-level EC reconstruction executor use daemon threads.

The default EC reconstruction executor also retires its worker after 60 seconds of inactivity while retaining single-worker task execution. Caller-supplied executors and existing explicit cleanup paths are unchanged. Applications still need to close streams to complete writes.

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-17254

How was this patch tested?

  • Added four isolated-JVM regression cases. Against the original code, each worker started successfully and the JVM remained alive past the 30-second exit timeout. With the fixes, all four JVMs exited normally.
  • Added an HDDS-10564 regression case using a real RpcClient write executor and a RatisBlockOutputStream against the mock datanode pipeline. Reversing the original daemon-thread setting makes the child JVM stay alive past the 30-second timeout; restoring the setting makes it exit normally. The shared stream setup and exit assertion live in TestClientThreadShutdown, with the higher-level test in TestRpcClient to avoid a module dependency cycle.
  • Added a regression case for idle default EC workers: it fails against the original implementation and passes with the fix. It also checks that the executor accepts new work after the previous worker retires.
  • The short-circuit cases mock native sockets or enable timer initialization without opening a native socket. The EC case activates the default executor directly. These tests isolate thread lifecycle rather than exercising a live cluster.
  • All 113 targeted tests passed across TestClientThreadShutdown, TestBlockDataStreamOutput, TestBlockInputStreamFactoryImpl, TestECBlockInputStream, TestECBlockReconstructedInputStream, and TestECBlockReconstructedStripeInputStream. The original five shutdown/idle cases took approximately 3 seconds in a standalone rerun. After adding Ratis coverage, all 184 tests across TestClientThreadShutdown and the full TestRpcClient class passed.
  • Repository checkstyle and the hdds-client RAT check passed. Repository-wide RAT found unrelated existing local files under dev-support, including Bats support files and prior reproduction build artifacts.

Validation used JDK 21 with -DskipShade -DskipRecon -DskipDocs.

Generated-by: Codex (GPT-6)

Change-Id: I72728254d74114c33e49f0e5e14d9c81e7577385
Copilot AI balanced review requested due to automatic review settings October 21, 2026 18:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

2 open issues
What changed in this PR

Updates Ozone client background thread creation to avoid non-daemon workers keeping the JVM alive after main returns, and adds regression tests that validate JVM shutdown behavior and EC worker retirement.

Changes:

  • Convert several client background workers (executors/timers) to daemon threads to prevent JVM shutdown blocking.
  • Replace the default EC reconstruction executor with a single-worker executor that retires after idle timeout.
  • Add isolated-JVM regression tests covering each affected worker plus EC idle retirement/reuse.
File Description
hadoop-hdds/​client/​src/​test/​java/​org/​apache/​hadoop/​hdds/​scm/​storage/​TestClientThreadShutdown.java Adds isolated-JVM tests ensuring client background workers don’t prevent process exit and EC worker retires when idle.
hadoop-hdds/​client/​src/​main/​java/​org/​apache/​hadoop/​ozone/​client/​io/​BlockInputStreamFactoryImpl.java Switches default EC reconstruction executor to a daemon-thread ThreadPoolExecutor with idle retirement.
hadoop-hdds/​client/​src/​main/​java/​org/​apache/​hadoop/​hdds/​scm/​storage/​DomainSocketFactory.java Makes the factory timer a daemon timer thread.
hadoop-hdds/​client/​src/​main/​java/​org/​apache/​hadoop/​hdds/​scm/​storage/​BlockDataStreamOutput.java Uses a daemon-thread single-thread executor for streaming write response handling.
hadoop-hdds/​client/​src/​main/​java/​org/​apache/​hadoop/​hdds/​scm/​XceiverClientShortCircuit.java Makes the short-circuit connection timer a daemon timer thread.

Review effort: Lite

Comment on lines +75 to +77
this(new ElasticByteBufferPool(), () -> new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(), new ThreadFactoryBuilder()
.setNameFormat("EC-reconstruction-%d").setDaemon(true).build()));
OzoneClientConfig socketConfig = conf.getObject(OzoneClientConfig.class);
socketConfig.setShortCircuit(true);
conf.setFromObject(socketConfig);
conf.set(OzoneClientConfig.OZONE_DOMAIN_SOCKET_PATH, "/tmp/ozone-client-shutdown.sock");
Change-Id: Ieddf3905300bcc3850ede5b33ce665869df648c1

@smengcl smengcl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Validate the retained client reference before signaling worker readiness, declare fields before the enum, and make the Ratis launcher client a local variable.

Co-authored-by: Codex (GPT-6)
Change-Id: I3b8d60c739f740937fe17ac6f36fdeb94aa05755
@smengcl
smengcl merged commit fa3c98f into apache:master Oct 22, 2026
106 of 109 checks passed
@smengcl

smengcl commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Thanks @jojochuang for the patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants