Skip to content

Close writable entry streams during async archive disposal - #1338

Merged
adamhathcock merged 3 commits into
masterfrom
copilot/fix-writable-archive-disposeasync
May 29, 2026
Merged

Close writable entry streams during async archive disposal#1338
adamhathcock merged 3 commits into
masterfrom
copilot/fix-writable-archive-disposeasync

Conversation

Copilot AI commented May 28, 2026

Copy link
Copy Markdown
Contributor

SaveToAsync on writable archives completed without releasing tracked entry streams on async disposal, leaving output files/directories locked. The sync path already closed these streams; the async path now matches that behavior.

  • Core fix (shared writable archive disposal path)

    • Added DisposeAsync override in AbstractWritableArchive.Async to close tracked writable entries (newEntries, removedEntries, modifiedEntries) after base.DisposeAsync().
  • Coverage across writable archive types

    • Added focused async regression tests for:
      • TarArchive
      • ZipArchive
      • GZipArchive
    • Each test adds an entry with closeStream: true, calls SaveToAsync, disposes asynchronously, and asserts the source stream is disposed.
  • Behavioral parity (sync vs async)

    • Async disposal now performs the same entry-stream cleanup already present in sync Dispose(), preventing lingering file handles after async save flows.
public override async ValueTask DisposeAsync()
{
    await base.DisposeAsync().ConfigureAwait(false);
    newEntries.Cast<Entry>().ForEach(x => x.Close());
    removedEntries.Cast<Entry>().ForEach(x => x.Close());
    modifiedEntries.Cast<Entry>().ForEach(x => x.Close());
}

Copilot AI changed the title [WIP] Fix writable archive DisposeAsync to close entry streams Close writable entry streams during async archive disposal May 28, 2026
Copilot AI requested a review from adamhathcock May 28, 2026 13:13
@adamhathcock
adamhathcock marked this pull request as ready for review May 28, 2026 14:36
Copilot AI review requested due to automatic review settings May 28, 2026 14:36

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.

Pull request overview

This PR fixes async disposal for writable archives so entry streams tracked during async save flows are closed like the synchronous disposal path.

Changes:

  • Adds DisposeAsync cleanup in AbstractWritableArchive for new, removed, and modified writable entries.
  • Adds async regression tests for Zip, Tar, and GZip writable archives to verify closeStream: true entry streams are disposed.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/SharpCompress/Archives/AbstractWritableArchive.Async.cs Adds async disposal cleanup for tracked writable archive entries.
tests/SharpCompress.Test/Zip/ZipArchiveAsyncTests.cs Adds Zip async disposal regression coverage.
tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs Adds Tar async disposal regression coverage.
tests/SharpCompress.Test/GZip/GZipArchiveAsyncTests.cs Adds GZip async disposal regression coverage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@adamhathcock
adamhathcock merged commit 01fe281 into master May 29, 2026
7 checks passed
@adamhathcock
adamhathcock deleted the copilot/fix-writable-archive-disposeasync branch May 29, 2026 08:05
github-actions Bot pushed a commit to Stella-sea/ryujinx-admin that referenced this pull request May 31, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [SharpCompress](https://github.com/adamhathcock/sharpcompress) | `0.48.1` → `0.49.1` | ![age](https://developer.mend.io/api/mc/badges/age/nuget/SharpCompress/0.49.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/SharpCompress/0.48.1/0.49.1?slim=true) |

---

### Release Notes

<details>
<summary>adamhathcock/sharpcompress (SharpCompress)</summary>

### [`v0.49.1`](https://github.com/adamhathcock/sharpcompress/releases/tag/0.49.1): - More fixes

[Compare Source](adamhathcock/sharpcompress@0.49.0...0.49.1)

#### What's Changed

- Close writable entry streams during async archive disposal by [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;1338](adamhathcock/sharpcompress#1338)
- Restore `WriteToDirectoryAsync` progress callbacks for solid 7z archives by [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;1340](adamhathcock/sharpcompress#1340)
- Try to fix global.json to avoid churn in locks by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1341](adamhathcock/sharpcompress#1341)
- Fix tar archive enumeration after fully reading entry streams by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1342](adamhathcock/sharpcompress#1342)

**Full Changelog**: <adamhathcock/sharpcompress@0.49.0...0.49.1>

### [`v0.49.0`](https://github.com/adamhathcock/sharpcompress/releases/tag/0.49.0): - Write Async fixes and more.

[Compare Source](adamhathcock/sharpcompress@0.48.1...0.49.0)

This should contain a lot of write async fixes and some breaking API changes that fix previous broke `net48` usage

#### What's Changed

- Rename IWriteableArchiveFactory.cs to IWritableArchiveFactory.cs by [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;1244](adamhathcock/sharpcompress#1244)
- Some API clean up from GPT 5.4 by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1243](adamhathcock/sharpcompress#1243)
- Release to master by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1267](adamhathcock/sharpcompress#1267)
- Fix three BLAKE2sp correctness bugs and eliminate allocations in hot path by [@&#8203;coderb](https://github.com/coderb) in [#&#8203;1266](adamhathcock/sharpcompress#1266)
- Corrected async examples. by [@&#8203;dlemstra](https://github.com/dlemstra) in [#&#8203;1277](adamhathcock/sharpcompress#1277)
- Fix setting invalid access time fails extraction by [@&#8203;aromaa](https://github.com/aromaa) in [#&#8203;1279](adamhathcock/sharpcompress#1279)
- Fix incorrect code examples in docs for sync/async usage by [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;1280](adamhathcock/sharpcompress#1280)
- Replace APPNOTE.TXT contents with reference link note by [@&#8203;puk06](https://github.com/puk06) in [#&#8203;1286](adamhathcock/sharpcompress#1286)
- Release to Master by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1274](adamhathcock/sharpcompress#1274)
- update docs for tar gap analysis and XZ usage by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1288](adamhathcock/sharpcompress#1288)
- Add a PooledMemoryStream to avoid allocating by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1275](adamhathcock/sharpcompress#1275)
- fix: Change LeaveStreamOpen default from true to false by [@&#8203;puk06](https://github.com/puk06) in [#&#8203;1293](adamhathcock/sharpcompress#1293)
- Fix usage of ReaderOptions and pre-defined values by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1295](adamhathcock/sharpcompress#1295)
- Enforce seekable, readable and writable on streams by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1297](adamhathcock/sharpcompress#1297)
- Add ArchiveInformation record for consolidated archive detection and capability inspection by [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;1299](adamhathcock/sharpcompress#1299)
- merge release to master by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1314](adamhathcock/sharpcompress#1314)
- Some clean up and test clean up by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1321](adamhathcock/sharpcompress#1321)
- Finish Write Async by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1323](adamhathcock/sharpcompress#1323)
- More complete Tar implementation: USTAR, PAX, etc. by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1289](adamhathcock/sharpcompress#1289)
- Add Polysharp and adjustments that do not break legacy frameworks by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1330](adamhathcock/sharpcompress#1330)
- Fix null `IVolume.FileName` for single-volume file-based archives by [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;1333](adamhathcock/sharpcompress#1333)
- Add skills by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1332](adamhathcock/sharpcompress#1332)
- add AOT smoke and missing tests by [@&#8203;adamhathcock](https://github.com/adamhathcock) in [#&#8203;1334](adamhathcock/sharpcompress#1334)

#### New Contributors

- [@&#8203;dlemstra](https://github.com/dlemstra) made their first contribution in [#&#8203;1277](adamhathcock/sharpcompress#1277)
- [@&#8203;aromaa](https://github.com/aromaa) made their first contribution in [#&#8203;1279](adamhathcock/sharpcompress#1279)
- [@&#8203;puk06](https://github.com/puk06) made their first contribution in [#&#8203;1286](adamhathcock/sharpcompress#1286)

**Full Changelog**: <adamhathcock/sharpcompress@0.48.1...0.49.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzguMCIsInVwZGF0ZWRJblZlciI6IjQzLjE3OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->

Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/123
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.

Writable archive DisposeAsync does not close entry streams

3 participants