[GH-ISSUE #4505] [Bug] Windows native handle finalization discards failed close ownership #1789

Closed
opened 2026-10-16 21:10:16 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @morluto on GitHub (Oct 16, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4505

Before submitting

  • Searched open and closed Windows snapshot/cleanup and CloseHandle ownership reports; #4502 covers POSIX descriptor creation and #4504 covers native primary error composition.
  • No credentials or sensitive target data included.

Area

Native analysis or decompilation

Observed behavior

Source-confirmed: native/windows/src/authority.hpp Handle.reset calls CloseHandle without checking its result, then replaces its stored value. Its destructor and move assignment use the same operation. Snapshot disposal uses reset before reopening the destination; snapshot completion destroys the source owner. A rejected native close therefore loses its exact owner and cannot be reported or retried.

Reproduction

NOT_ENOUGH_INFO for natural or injected native Windows reproduction. Inspected Handle.reset and snapshot consumers. Proposed native fault checks: source close and destination close rejection after completed and failed copy; mixed handles; retry using only unreleased exact owners. No actual failed CloseHandle or leak count observed.

Expected behavior

Explicit finalization checks close results and retains exact unresolved handle ownership. Physical copy/hash/failure outcome remains separate from cleanup. Completion waits for admitted finalization and cleanup can be retried through the owner.

Impact and scope

Shared Windows native Handle lifetime, concretely consumed by private-runtime snapshot. A failed close can be silently forgotten. Natural occurrence, frequency and additional consumers affected require investigation. Native CloseHandle failure semantics need verification before retry design; never blindly retry a reused numeric handle.

REA version

6.5.0; source base fe2a398dd9.

Runtime and platform

Source analysis on macOS arm64; Windows native runtime not executed.

Target and artifact context

Digest-committed private snapshot used for Ghidra import; source bytes are read-only.

Interface

Shared Windows private runtime / Ghidra CLI and MCP startup.

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

authority.hpp Handle.reset: if(valid()) CloseHandle(value_); value_=next. filesystem.cc disposeSnapshot uses file.reset() around line492; SnapshotWork owns source and destination handles and is destroyed after completeSnapshot. The code exposes no checked-close result or retained failed close owner at these stages.

Typed outcome or recovery expected

Preserve exact owned resources while cleanup is unconfirmed, and distinguish terminal invalidity from a retryable close failure using native evidence. Runtime tree removal alone does not prove every admitted descriptor released.

Analysis or suspected cause

Best-effort RAII destruction is also used as explicit operational finalization. Introduce a checked owner operation at the producing native boundary and audit its consumers; keep destructor constraints and numeric handle reuse explicit.

Additional context

Source-only finding from lifecycle audit. #4504 separately fixes native error composition. No Windows build, native fault injection, or real-provider failure reproduction claimed. Implementation remains pending native ownership design and applicable verification.

Originally created by @morluto on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4505 ### Before submitting - [x] Searched open and closed Windows snapshot/cleanup and CloseHandle ownership reports; #4502 covers POSIX descriptor creation and #4504 covers native primary error composition. - [x] No credentials or sensitive target data included. ### Area Native analysis or decompilation ### Observed behavior Source-confirmed: native/windows/src/authority.hpp Handle.reset calls CloseHandle without checking its result, then replaces its stored value. Its destructor and move assignment use the same operation. Snapshot disposal uses reset before reopening the destination; snapshot completion destroys the source owner. A rejected native close therefore loses its exact owner and cannot be reported or retried. ### Reproduction NOT_ENOUGH_INFO for natural or injected native Windows reproduction. Inspected Handle.reset and snapshot consumers. Proposed native fault checks: source close and destination close rejection after completed and failed copy; mixed handles; retry using only unreleased exact owners. No actual failed CloseHandle or leak count observed. ### Expected behavior Explicit finalization checks close results and retains exact unresolved handle ownership. Physical copy/hash/failure outcome remains separate from cleanup. Completion waits for admitted finalization and cleanup can be retried through the owner. ### Impact and scope Shared Windows native Handle lifetime, concretely consumed by private-runtime snapshot. A failed close can be silently forgotten. Natural occurrence, frequency and additional consumers affected require investigation. Native CloseHandle failure semantics need verification before retry design; never blindly retry a reused numeric handle. ### REA version 6.5.0; source base fe2a398dd9ab290ba6cb3411403d319cec8d07a2. ### Runtime and platform Source analysis on macOS arm64; Windows native runtime not executed. ### Target and artifact context Digest-committed private snapshot used for Ghidra import; source bytes are read-only. ### Interface Shared Windows private runtime / Ghidra CLI and MCP startup. ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence authority.hpp Handle.reset: if(valid()) CloseHandle(value_); value_=next. filesystem.cc disposeSnapshot uses file.reset() around line492; SnapshotWork owns source and destination handles and is destroyed after completeSnapshot. The code exposes no checked-close result or retained failed close owner at these stages. ### Typed outcome or recovery expected Preserve exact owned resources while cleanup is unconfirmed, and distinguish terminal invalidity from a retryable close failure using native evidence. Runtime tree removal alone does not prove every admitted descriptor released. ### Analysis or suspected cause Best-effort RAII destruction is also used as explicit operational finalization. Introduce a checked owner operation at the producing native boundary and audit its consumers; keep destructor constraints and numeric handle reuse explicit. ### Additional context Source-only finding from lifecycle audit. #4504 separately fixes native error composition. No Windows build, native fault injection, or real-provider failure reproduction claimed. Implementation remains pending native ownership design and applicable verification.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#1789
No description provided.