Skip to content

fix(foundation): close the input when the Extractor constructor raises (#2100) - #2106

Merged
JarryShaw merged 1 commit into
mainfrom
fix/2100-close-input-on-constructor-error
Oct 23, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/2100-close-input-on-constructor-error

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • fix — bug fixes

Description of your pull request and other information

Closes #2100. When an engine raised out of Extractor.__init__ → run → record_frames, for example a FormatError on a packet block before any interface, only KeyboardInterrupt cleaned up. An input the Extractor had opened stayed open until GC, and on Windows that blocks deleting the file (WinError 32).

  • Why not _cleanup(), as the issue proposed: for an unknown magic number, run() raises before _exeng exists, so _cleanup() would mask the FormatError with an AttributeError. It would also close a half-started engine and end a flow trace that never ran.
  • Fix: the magic read and run() sit in a try that, on any exception, closes the input only if the Extractor owns it (the Extractor._cleanup closes the caller-supplied stream and leaks the file it opened itself #610 rule), detaches the finaliser, and re-raises. A second call is harmless.
  • Test: test_extraction_constructor_raises_2100_unit records the handles the Extractor opens. Without the fix, the packet-block-before-interface case leaves its file open. It also pins that the unknown-format error is not masked and that a caller's file or stream stays open. test_extraction_ownership passes.

#2100)

Only a KeyboardInterrupt reached _cleanup, so a FormatError out of __init__
left an input the Extractor opened open until collection, which Windows will
not delete. The magic read and run() now release an owned input and detach
its finaliser on any exception; a caller's stream stays open. _cleanup itself
is not called: an unknown format raises before any engine exists.
@JarryShaw JarryShaw added bug Issues reporting a defect (set by the bug report template; a default, not an assessment) review: running A cross-review is in flight against the current head - no verdict yet labels Oct 23, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO at bcca8aefa (Sonnet review).

  • Test: test_a_format_error_while_reading_frames_closes_the_input fails with extraction.py reverted and passes with the fix. Neighbouring tests pass.
  • Why not _cleanup(): the reviewer swapped in self._cleanup() as a mutant. The unknown-format case then failed with AttributeError: … no attribute '_exeng', masking the FormatError.
  • Propagation: a bare raise keeps the exception's type, message and traceback. The KeyboardInterrupt path still runs _cleanup() first, and the second close is idempotent.
  • Remaining leak, not made worse by this PR: if the engine raises after _exeng exists, _exeng.close() is never called, so PyShark's temp capture stays open. Tracked separately.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 23, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Coverage: 91.54% (unit tier, Python 3.15, bcca8aefa, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 2 95.16%
pcapkit/const 19599 880 2618 866 92.12%
pcapkit/corekit 2565 71 812 37 96.56%
pcapkit/dumpkit 282 3 102 3 98.44%
pcapkit/foundation 2936 23 1024 25 98.79%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 17414 219 4574 185 98.14%
pcapkit/toolkit 869 36 298 10 95.20%
pcapkit/utilities 473 7 136 5 98.03%
pcapkit/vendor 4432 1988 1018 167 51.87%

Per-file detail: the coverage-html artifact of this run.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Ready to merge at bcca8aefa.

  • Review: the Sonnet review is GOOD TO GO.
  • CI: every blocking check passed (Required checks passed SUCCESS). The 3.8–3.10 KTLO legs carry no warnings.
  • Ordering: the tests/foundation plain-unittest ordering leg passed on a scratch merge into main: 713 tests, 0 failures.
  • Base: the head is behind main only by test-only commits (aeb4aadd3, test(tier-guard): the xdist probe races latest_tier_paths on Windows, where the tier-guard lock is a no-op #2114) and the build-only dispatch workflows (c5081fbfe). Neither touches extraction.py, and the scratch merge was clean.

This closes #2100. #2107 (closing the engine too) follows once it merges.

@JarryShaw
JarryShaw merged commit 04a15e9 into main Oct 23, 2026
65 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Oct 23, 2026
@JarryShaw
JarryShaw deleted the fix/2100-close-input-on-constructor-error branch October 23, 2026 21:54
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 23, 2026
@JarryShaw JarryShaw added this to the PyPCAPKit v1.5 milestone Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Issues reporting a defect (set by the bug report template; a default, not an assessment)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(foundation): Extractor keeps its input open when the constructor's run() raises

1 participant