Skip to content

HDDS-16504. Datanode startup can hang indefinitely when Ratis group recovery stalls - #11264

Merged
smengcl merged 6 commits into
apache:masterfrom
devmadhuu:HDDS-16504
Sep 21, 2026
Merged

smengcl merged 6 commits into
apache:masterfrom
devmadhuu:HDDS-16504

Conversation

@devmadhuu

@devmadhuu devmadhuu commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Datanode startup can hang indefinitely when container initialization stalls without throwing — typically when the Ratis write channel is recovering Raft groups and a read blocks on a failing volume. OzoneContainer.start() never returns, so the datanode never registers/heartbeats, logs endpoint‑task timeouts forever, and re‑hits the same stall on restart.

This complements HDDS‑16425 (which handles init failures that throw); this covers the hang case.

What is the link to the Apache JIRA

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

How was this patch tested?

  • New unit test TestOzoneContainer#testInitTimeoutFailsStartupWhenInitializationStalls (stall → IOException caused by TimeoutException, then fails fast as FAILED)
  • test-compile and checkstyle:check on hadoop-hdds/container-service

…ecovery stalls (add a timeout/watchdog around container initialization) - Initial Commit
@adoroszlai adoroszlai changed the title HDDS-16504. Datanode startup can hang indefinitely when Ratis group recovery stalls (add a timeout/watchdog around container initialization) HDDS-16504. Datanode startup can hang indefinitely when Ratis group recovery stalls Sep 19, 2026
@devmadhuu
devmadhuu marked this pull request as ready for review September 19, 2026 07:38
Comment on lines +608 to +613
} catch (TimeoutException e) {
// Best-effort interrupt; a thread blocked on disk I/O may not respond,
// but the datanode will shut down once the caller marks startup FAILED.
initFuture.cancel(true);
throw new IOException("OzoneContainer initialization did not complete within " + initTimeout
+ ". Failing datanode startup; a stalled Ratis group recovery or volume I/O is the likely cause.", e);

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.

Could we prevent initialization from continuing after the timeout, and coordinate cleanup with the surviving initializer?

cancel(true) and shutdownNow() only interrupt the worker. Ratis 3.2.1's RaftServerProxy.startImpl() waits on CompletableFuture.join(), which ignores interruption. If recovery completes later, initializeContainerServices() continues starting services even though startup is already FAILED and shutdown may have cleaned up their dependencies.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, thanks — you're right, and I confirmed it. cancel(true)/shutdownNow() only interrupt the worker, and the interrupt is ignored by the stalled Ratis RaftServerProxy.startImpl() CompletableFuture.join(). I have handled in different way using separate watch thread. Kindly have a re-look.

@devmadhuu
devmadhuu requested a review from smengcl September 19, 2026 16:11
@devmadhuu
devmadhuu requested a review from smengcl September 21, 2026 10:42

@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.

looks good now. Thanks @devmadhuu

@smengcl
smengcl merged commit 8621653 into apache:master Sep 21, 2026
88 of 89 checks passed
@smengcl

smengcl commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Thanks @devmadhuu for the patch.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants