Skip to content

Close driver and agent file streams even when an exception interrupts them - #56

Open
lgnap wants to merge 1 commit into
antoinevalentinHA:masterfrom
lgnap:fix/issue-10-driver-stream-leaks
Open

lgnap wants to merge 1 commit into
antoinevalentinHA:masterfrom
lgnap:fix/issue-10-driver-stream-leaks

Conversation

@lgnap

@lgnap lgnap commented Sep 11, 2026

Copy link
Copy Markdown

What

Three file streams in driver and agent were opened and closed by hand. Any exception raised between the open and the .close() skipped the close and leaked the handle. On Windows a leaked handle keeps the file locked, so the very pack folder a transfer was building could then neither be finished nor removed.

Site Stream
CipherUtils.addBootFileV2 ri input + bt output
RawStoryTellerAsyncDriver.dumpSector sector dump output
UnofficialMetadataAdvice thumbnail cache output

All three now use try-with-resources. No behaviour change on the happy path.

Why no failure-path test

There is no input that makes these methods fail between opening a stream and closing it: a missing/unreadable ri fails in the FileInputStream constructor before any handle exists, a short ri is ciphered without error, and a 64-byte write has no reachable failure short of a full disk. Reaching the leak would need a seam the production code does not need, so this is a correctness fix by inspection — the same status the repo already gives the getFolderSize closing (see FilesWalkResourceLeakTest#measuringFolderSizeReleasesTheTree).

Tests

addBootFileV2 had no test at all. BootFileStreamLifecycleTest (5 tests) pins its nominal contract so the rewrite cannot have altered it: bt is the 64-byte ciphered prefix of ri, it depends on the device UUID, a second run overwrites rather than appends, a short ri yields a short bt, and both files are deletable on return (the Windows-observable consequence of a closed handle).

Locally: mvn -B -Dskip.installnodeyarn=true -Dskip.yarn=true test → 322 run, 0 failures, 0 errors, 39 skipped (the FAT32 opt-in classes). git diff --exit-code clean after the build. Frontend untouched.

Tracked in lgnap#10.

🤖 Generated with Claude Code

…rupts them

Three file streams were closed by hand after their read or write, so any
exception raised in between skipped the close and leaked the handle. On
Windows a leaked handle keeps the file locked, and the pack folder the
transfer was building could then neither be finished nor removed.

- CipherUtils.addBootFileV2: the `ri` input and `bt` output streams
- RawStoryTellerAsyncDriver.dumpSector: the sector dump output stream
- UnofficialMetadataAdvice: the thumbnail cache output stream

All three now use try-with-resources. No change on the happy path.

The failure path cannot be reached from outside without a seam the
production code does not need (a missing `ri` fails before the handle
exists, a short one is ciphered without error), so this is a correctness
fix by inspection. BootFileStreamLifecycleTest pins the nominal contract
of addBootFileV2, which had no test: the shape of `bt`, its dependence on
the device UUID, idempotence, and that both files are released on return.

Closes #10

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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