[ 
https://issues.apache.org/jira/browse/HDDS-17254?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated HDDS-17254:
----------------------------------
    Labels: pull-request-available  (was: )

> Client-side non-daemon executors and timers can prevent JVM shutdown
> --------------------------------------------------------------------
>
>                 Key: HDDS-17254
>                 URL: https://issues.apache.org/jira/browse/HDDS-17254
>             Project: Apache Ozone
>          Issue Type: Bug
>          Components: EC Client, Ozone Client
>            Reporter: Wei-Chiu Chuang
>            Priority: Major
>              Labels: pull-request-available
>
> h2. Problem
> HDDS-10564 / [PR #6418|https://github.com/apache/ozone/pull/6418] made 
> RpcClient output-stream executors use daemon threads so an unclosed 
> FileSystem/client would not keep a command-line JVM alive. A source audit 
> found four other client-side executor/timer creation sites with the same 
> potential shutdown risk.
> This report is based on source inspection at 
> d0949f291791c399f3e54409fcb92656a80597a4. JVM-exit hangs have not yet been 
> reproduced in a subprocess test. Not every invocation starts the relevant 
> worker: the conditions for each path are listed below.
> h2. Affected paths
> h3. 1. Ratis streaming writes: BlockDataStreamOutput
> The constructor creates its response executor with 
> Executors.newSingleThreadExecutor(), whose default thread factory creates 
> non-daemon threads. This is separate from RpcClient.writeExecutor, so 
> HDDS-10564 does not cover it. After an asynchronous response starts the 
> worker, an abandoned/unclosed streaming output can keep the JVM alive. Normal 
> close calls cleanup in finally, and cleanup shuts down the executor.
> * Executor creation: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/BlockDataStreamOutput.java#L195
> * Normal close/cleanup: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/BlockDataStreamOutput.java#L689
> * Executor shutdown: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/BlockDataStreamOutput.java#L736
> h3. 2. Short-circuit reads: per-connection timer
> XceiverClientShortCircuit.connect() creates new Timer(prefix + "-Timer") 
> without the daemon argument. The timer thread starts when the connection is 
> established. If client cleanup is omitted, it can keep the JVM alive. Normal 
> close cancels the timer.
> * 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientShortCircuit.java#L143
> h3. 3. Short-circuit reads: singleton DomainSocketFactory timer
> When short-circuit reads are configured and native support is available, 
> DomainSocketFactory creates new Timer(name) without the daemon argument. This 
> is a second non-daemon timer, separate from the connection timer above. 
> Factory close cancels it, but an unclosed client/factory can leave it alive.
> * Creation: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/DomainSocketFactory.java#L160
> * Cancellation: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/DomainSocketFactory.java#L272
> h3. 4. Default low-level EC reader factory
> BlockInputStreamFactoryImpl's no-argument constructor supplies 
> Executors::newSingleThreadExecutor. If an EC reconstruction reader is 
> instantiated through this default factory and executes reconstruction work, 
> it can start non-daemon workers. The reconstruction stream's close method 
> does not shut down the supplied executor. The normal RpcClient path supplies 
> its own daemon executors and is not affected by this default-factory creation 
> site.
> * Default factory: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/ozone/client/io/BlockInputStreamFactoryImpl.java#L70
> * Reconstruction executor acquisition: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/ozone/client/io/ECBlockInputStreamFactoryImpl.java#L95
> * Reconstruction stream close: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-hdds/client/src/main/java/org/apache/hadoop/ozone/client/io/ECBlockReconstructedStripeInputStream.java#L738
> * A production caller of the default factory is the checksum-verification 
> tool: 
> https://github.com/apache/ozone/blob/d0949f291791c399f3e54409fcb92656a80597a4/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/replicas/ChecksumVerifier.java#L61
> h2. Expected behavior / suggested fix
> Client housekeeping workers should not prevent JVM termination solely because 
> a caller has finished its work but omitted explicit cleanup. Apply the 
> daemon-thread principle used by HDDS-10564 to the affected background 
> executors/timers, while preserving normal close/cancel behavior.
> * Use a named daemon ThreadFactory for the streaming response executor.
> * Use daemon timers for both short-circuit timer sites.
> * Give the default EC reconstruction executor an explicit lifecycle/owner and 
> daemon threads. Do not indiscriminately shut down caller-supplied shared 
> executors from an individual stream's close method.
> h2. Validation needed
> Add isolated subprocess tests with bounded exit timeouts:
> # Start streaming response work, omit stream/client close, return from main, 
> and verify the JVM exits.
> # Establish a short-circuit connection, omit client/factory close, return 
> from main, and verify both timer threads do not retain the JVM (requires 
> native short-circuit prerequisites).
> # Trigger EC reconstruction through the no-argument factory, close the 
> stream, and verify no orphan executor keeps the JVM alive; also check the 
> abandoned-stream case.
> # Verify explicit cleanup still terminates/releases the owned resources and 
> does not break shared executors.
> Daemon workers do not replace application responsibility to flush and close 
> streams. No data-durability guarantee is inferred from changing thread daemon 
> status.
> Related prior fix: HDDS-10564.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to