Cancelling a mirror (user interrupt, -E time limit) while a URL is inside the delayed-type-check flow orphans the on-disk X.N.delayed placeholder. hts_wait_delayed() (htsparse.c) resolves the final type, recomputes the savename, and re-adds the URL under its real name. If that re-add is refused ("File not added due to mirror cancel"), or the mirror ends before the flow completes, the placeholder file with its partial body bytes stays in the output tree. By then the slot's url_sav already carries the final name, so every cleanup path keyed on IS_DELAYED_EXT(url_sav) (back_delete, back_finalize, the #482 abort sweep) is blind to the on-disk name.
This predates #482: it reproduces on 3.49-10 with a plain smooth stop, and surfaces as stray files like trickle/p3.bin.4.delayed (partial content) after a cancelled crawl.
Reproduce (~10% per run): run tests/34_local-maxtime.test pinned to one busy CPU (taskset -c 0 plus a few competing busy loops). An strace'd timeline shows the original transfer writing p2.bin.3.delayed, hts_wait_delayed() re-adding under p2.bin right as the stop lands, the refusal, and no unlink afterward.
Pointers: the cache-miss/re-add branch of hts_wait_delayed() keeps the old savename only in a back_copy_static() copy (delayed_back); a cancel between back_maydelete() and the re-add drops the last reference to the on-disk name. htsback.c has a back_delayed_discard() helper (from #482) that fits the cleanup.
Until this is fixed, 34_local-maxtime.test skips the .delayed leftover audit (local-crawl.sh --skip-delayed-audit).
Cancelling a mirror (user interrupt,
-Etime limit) while a URL is inside the delayed-type-check flow orphans the on-diskX.N.delayedplaceholder.hts_wait_delayed()(htsparse.c) resolves the final type, recomputes the savename, and re-adds the URL under its real name. If that re-add is refused ("File not added due to mirror cancel"), or the mirror ends before the flow completes, the placeholder file with its partial body bytes stays in the output tree. By then the slot'surl_savalready carries the final name, so every cleanup path keyed onIS_DELAYED_EXT(url_sav)(back_delete,back_finalize, the #482 abort sweep) is blind to the on-disk name.This predates #482: it reproduces on 3.49-10 with a plain smooth stop, and surfaces as stray files like
trickle/p3.bin.4.delayed(partial content) after a cancelled crawl.Reproduce (~10% per run): run
tests/34_local-maxtime.testpinned to one busy CPU (taskset -c 0plus a few competing busy loops). An strace'd timeline shows the original transfer writingp2.bin.3.delayed,hts_wait_delayed()re-adding underp2.binright as the stop lands, the refusal, and no unlink afterward.Pointers: the cache-miss/re-add branch of
hts_wait_delayed()keeps the old savename only in aback_copy_static()copy (delayed_back); a cancel betweenback_maydelete()and the re-add drops the last reference to the on-disk name. htsback.c has aback_delayed_discard()helper (from #482) that fits the cleanup.Until this is fixed,
34_local-maxtime.testskips the.delayedleftover audit (local-crawl.sh--skip-delayed-audit).