Skip to content

HDDS-16949. BackgroundService stops permanently when getTasks() throws a RuntimeException - #11496

Open
smengcl wants to merge 2 commits into
apache:masterfrom
smengcl:HDDS-16949-flaky
Open

smengcl wants to merge 2 commits into
apache:masterfrom
smengcl:HDDS-16949-flaky

Conversation

@smengcl

@smengcl smengcl commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Generated-by: Claude Code (Sonnet 5.5)

What changes were proposed in this pull request?

BackgroundService.PeriodicalTask#run called getTasks() outside any try/catch. The task is scheduled with scheduleWithFixedDelay, which silently cancels all later executions when a run throws. DirectoryDeletingService#getTasks iterates the snapshot chain without a lock, so a concurrent snapshot purge makes the iterator throw NoSuchElementException, and the service then never runs again on that OM. This is what made TestSnapshotDeletingServiceIntegrationTest#testSnapshotWithFSO time out waiting for deep cleaning.

This patch catches RuntimeException from getTasks(), logs it and retries in the next interval, so one bad cycle cannot cancel the schedule of any background service. Making the snapshot chain iteration itself race safe is left as a follow up.

What is the link to the Apache JIRA

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

How was this patch tested?

Added TestBackgroundService#testServiceKeepsRunningAfterGetTasksThrows, where getTasks() throws on the first call. It fails with a timeout without the fix and passes with it. TestBackgroundService (3 tests) and checkstyle pass locally.

  • 10x10 flaky-test-check on this branch: in progress (an earlier run on the previous commit, before the test only changed its thrown exception type, passed 100/100)

🤖 Generated with Claude Code

…s a RuntimeException

PeriodicalTask#run called getTasks() outside any try/catch. Since the task is
scheduled with scheduleWithFixedDelay, an exception escaping run() silently
cancels all later executions. For example DirectoryDeletingService#getTasks
iterates the snapshot chain, and a concurrent snapshot purge makes the
iterator throw NoSuchElementException, after which the service never runs
again on that OM.

Catch RuntimeException from getTasks(), log it and retry in the next interval.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings October 12, 2026 18:19

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 findings
What changed in this PR

Prevents BackgroundService periodic execution from being permanently cancelled when getTasks() throws at runtime, which previously caused background services to stop silently and led to test timeouts.

Changes:

  • Catch and log RuntimeException from BackgroundService.PeriodicalTask#run when calling getTasks(), then return to allow the next scheduled interval to proceed.
  • Add a regression test ensuring the service continues running after an initial getTasks() failure.
File Description
hadoop-hdds/​framework/​src/​main/​java/​org/​apache/​hadoop/​hdds/​utils/​BackgroundService.java Wraps getTasks() in try/catch to prevent scheduled task cancellation on runtime exceptions.
hadoop-hdds/​framework/​src/​test/​java/​org/​apache/​hadoop/​util/​TestBackgroundService.java Adds a test verifying periodic scheduling continues after getTasks() throws once.

🧠 Review effort: Lite


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

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

Approve. Catching RuntimeException from getTasks() in PeriodicalTask.run() is the right framework-level fix: scheduleWithFixedDelay stops scheduling after an uncaught throw, which matches the DDS outage when snapshot-chain iteration failed mid-getTasks.

The unit test cleanly proves the schedule survives a failed first getTasks() cycle. This is defense in depth alongside HDDS-16954 (#11500), which fixes the iterator race itself—both should land.

@priyeshkaratha priyeshkaratha left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the patch @smengcl and changes LGTM

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.

4 participants