Skip to content

Harden background compressor against stalled native work - #23

Draft
marcmy wants to merge 3 commits into
masterfrom
agent/harden-background-compressor-stalls
Draft

Harden background compressor against stalled native work#23
marcmy wants to merge 3 commits into
masterfrom
agent/harden-background-compressor-stalls

Conversation

@marcmy

@marcmy marcmy commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • expose lightweight progress state from Core.Compactor so the background watcher can tell whether work is advancing and identify the active phase/file
  • add a 30-minute active no-progress watchdog; time spent intentionally paused does not count
  • give cancellation 5 seconds to finish cleanly, then detach a non-returning native task instead of blocking the watcher forever
  • keep a detached compactor alive until its task actually exits, preserving the disposal-safety rule introduced in PR Fix watcher idle resume and cancellation #1
  • quarantine a folder while an earlier detached native compression task is still running so a later watcher run cannot overlap work on the same folder
  • make pause/resume/cancel access to the active compactor safer and tolerate cancellation races

Root cause

PR #1 fixed the cancellation/disposal race and idle-resume lifecycle, but the watcher still awaited Core.Compactor.RunAsync indefinitely. Compactor ultimately performs synchronous file/native work (File.OpenHandle / WofSetFileDataLocation) that cannot be interrupted by the managed cancellation token once the call is already executing. If that operation never returns, the folder's IsWorking cleanup cannot run and the watcher remains stuck on that folder.

Behavior after this change

Normal cancellation still follows the ordinary cooperative path. If Windows does not return from the current native operation within the grace period, CompactGUI releases the watcher/UI without disposing native state that may still be executing. The orphaned task owns its compactor until it exits, and that folder is skipped by later background runs in the meantime.

A genuinely idle background operation that reports no progress for 30 active minutes is cancelled through the same safe path. Watchdog warnings include the current phase and file to make another occurrence diagnosable.

Validation

  • diff is limited to CompactGUI.Core/Compactor.cs and CompactGUI.Watcher/BackgroundCompactor.vb
  • branch starts from current master
  • Windows x64 restore and self-contained publish: passed
  • packaging and artifact upload: passed
  • supply-chain audit: passed

Runtime checks

  1. Let a normal background run complete and verify folder state clears normally.
  2. Become active during an idle-only run, remain active longer than a watchdog poll, then become idle and verify the run resumes rather than timing out due to paused time.
  3. Cancel during analysis and between files and verify the watcher returns to idle.
  4. Cancel while a native file operation is artificially delayed/non-returning and verify the UI releases after the grace period without a crash.
  5. While such a detached operation remains alive, verify the same folder is skipped by subsequent background runs; once it exits, verify the folder becomes eligible again.
  6. Verify watchdog logs identify phase/file when no progress exceeds the configured threshold.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant