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

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

> DirectoryDeletingService can NPE on a transient Ratis submit failure (masked 
> by BackgroundService catch)
> --------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-16440
>                 URL: https://issues.apache.org/jira/browse/HDDS-16440
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Assignee: Huang Kuan Hao
>            Priority: Minor
>              Labels: pull-request-available
>         Attachments: HDDS-16440.001.patch
>
>
> h3. Finding
> A missing null check turns a tolerated transient Ratis submit failure 
> (ServiceException producing a null response) into an uncaught NPE 
> dereferencing resp.getSuccess() in the DirectoryDeletingService background 
> task. Masked by BackgroundService.run()'s unconditional catch(Throwable), 
> which logs and reschedules next interval, and nothing durable is written; 
> absent that guard the NPE would abort the run and risk stalling the periodic 
> deletion loop (liveness, no data corruption).
> h3. Classification
> * Verdict: MASKED
> * Severity: Medium
> * Source: Specula TLA+ model checking and confirmation debate, finding CR-5
> h3. Reproduce
> {noformat}
> Ozone commit: 9fbf9ee0cb1bd2f5f5d437b6719ebbe5309351fb
> Specula:      v1.1.0 (commit c6aa3dfa)
> Target:       om-fso-recursive-deletion
> Guidance:     
> campaigns/ozone-9fbf9ee/targets/005-om-fso-recursive-deletion/.prompt-extra.md
> {noformat}
> {code:none}
> specula run --agent=claude-code --effort=high --keep-original 
> --max-parallel=2 \
>   --enable-reviews --confirm-debate --tlc-memory-limit=28G 
> --tlc-worker-limit=8 \
>   "om-fso-recursive-deletion|apache/ozone|Java|Use the target-specific 
> .prompt-extra.md"
> {code}
> Discovered under HDDS-16429 (Specula TLA+ verification effort). The TLA+ 
> specification, counterexample, and confirmation debate live in the Specula 
> run artifacts.
> Generated with Specula (Claude Opus 4.8).
> h3. Steps to reproduce
> # OM is leader and the DirectoryDeletingService background task runs with 
> pending deleted directories, so enumeration builds a non-empty purge-path 
> list.
> # At batch flush, the OM Ratis submit fails transiently (leader step-down / 
> not-leader / timeout / interrupt during OM shutdown). 
> OzoneManagerRatisServer.submitRequest throws ServiceException.
> # submitPurgeRequest catches the ServiceException, logs "PurgePaths request 
> failed. Will retry at next run.", and returns null.
> # submitPurgePathsWithBatching then evaluates resp.getSuccess() on that null 
> response, throwing NullPointerException.
> # The NPE is a RuntimeException that none of the enclosing catch blocks 
> (which catch only IOException / ExecutionException / InterruptedException) 
> handle, so it propagates out of DirDeletingTask.call() and aborts the whole 
> directory-deleting run instead of the intended "skip, retry next run".
> Reproduced in a unit test that spies the service, stubs submitRequest to 
> throw ServiceException at its real seam, and drives the package-visible 
> optimizeDirDeletesAndSubmitRequest with a non-empty purge list. Without the 
> fix the call throws NullPointerException.
> h3. Root cause
> submitPurgeRequest (DirectoryDeletingService) returns null on 
> ServiceException (a normal, expected transient submit failure it explicitly 
> catches and logs). Its caller submitPurgePathsWithBatching dereferences the 
> response unconditionally with resp.getSuccess() at both the mid-loop batch 
> flush and the final batch flush, so a null response causes a 
> NullPointerException. The intended behavior (return an empty list, retry next 
> run) is defeated: the run dies instead of retrying.
> h3. Suggested fix
> Null-check the response at both submitPurgePathsWithBatching flush sites: 
> treat a null response the same as a failed submit (stop batching and return 
> the empty list), so a transient submit failure ends the run gracefully and 
> the pending directories are retried on the next run. See 
> [^HDDS-16440.001.patch]. The patch adds 
> testPurgeDirectoriesSubmitFailureIsTolerated, which reproduces the NPE 
> without the fix and passes with it.
> This finding is masked in production: the aborted run's un-purged directories 
> remain in the deleted-directory table and are retried on the next scheduled 
> run, so the effect is a delayed reclamation of one run rather than permanent 
> loss. The fix removes the abort so the retry path is taken directly.
> Patch is an AI-drafted proposal (Specula + Claude); pending human build, full 
> test, and review before merge.



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