[GH-ISSUE #4495] [Bug] Dyld resolution duplicates blocking file admission and loses descriptor cleanup outcomes #1781

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

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

Before submitting

  • Searched open/closed dylib, dyld and DylibResolutionReader reports, plus open related PRs. No matching descriptor-lifecycle report found.
  • No credentials or sensitive target data included.

Area

Evidence, artifacts, or reconstruction

Observed behavior

Source-confirmed finding; runtime reproduction not yet performed. DylibResolutionReader.ts independently opens files for magic probing, Mach-O header parsing and final hashing using blocking O_RDONLY | O_NOFOLLOW, then closes in finally. A close rejection replaces a read failure or completed observation and leaves no retained cleanup owner. The outer catch also replaces any failure with cancellation if the signal has subsequently aborted. The final hash close has no post-close cancellation check.

Reproduction

NOT_ENOUGH_INFO: no historical caller failure or live Mach-O target reproduction is available. Inspected the three raw open/read/finally-close paths and the outer catch at the source revision below. Proposed controlled checks: real descriptor close rejection after IO failure; cancellation during the final digest close; regular pathname replaced by FIFO between enumeration and open.

Expected behavior

AGENTS.md and docs/tool-design.md#own-the-lifecycle require nonblocking regular-file admission, exact retained cleanup ownership, preserving primary failures and caller cancellation reasons, and observing cancellation after final awaited cleanup. All three readers should use the shared file owner rather than duplicate admission and finalization.

Impact and scope

Source-derived: all trace_dylib_resolution paths use these readers. A substituted FIFO can block a bundle magic probe or image/hash read; failed close can lose the primary outcome and retry capability; finalization cancellation can report success. Natural occurrence and native Windows behavior are unknown.

REA version

6.5.0; base fe2a398dd9 with ongoing local audit changes.

Runtime and platform

Source analysis on macOS arm64; pinned Node24.18.0. Runtime reproduction not claimed.

Target and artifact context

Mach-O executable and bundle dyld path resolution; read-only files.

Interface

Shared provider used by CLI/MCP; source audit only at filing.

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

src/artifacts/apple/DylibResolutionReader.ts: startsWithMachoMagic, readImage and fileSha256 each own a raw descriptor with an unqualified finally-close. traceDylibResolution catch guesses cancellation from later signal state; fileSha256 returns through its final close. src/artifacts/ArtifactProvider.ts already owns an ArtifactResourceScope but does not pass it into dyld resolution. These are source-derived observations, not measured leak counts or runtime errors.

Typed outcome or recovery expected

Keep original IO failure and exact cancellation cause. Preserve completed observations separately from cleanup uncertainty; retain the exact failed descriptor for retry through provider close. Reject special files without waiting for a writer.

Analysis or suspected cause

Duplicated file admission/finalization instead of the shared nonblocking regular-file owner, plus downstream interpretation of current signal state. Proposed correction is one owning dyld file-access boundary using existing artifact resource and cleanup leases.

Additional context

Adjacent to #4483 (read-stream precedence) and #4475 (firmware descriptor lifetime); this independent dyld reader is not corrected by those changes. Verification results will be recorded separately after execution.

Originally created by @morluto on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4495 ### Before submitting - [x] Searched open/closed dylib, dyld and DylibResolutionReader reports, plus open related PRs. No matching descriptor-lifecycle report found. - [x] No credentials or sensitive target data included. ### Area Evidence, artifacts, or reconstruction ### Observed behavior **Source-confirmed finding; runtime reproduction not yet performed.** `DylibResolutionReader.ts` independently opens files for magic probing, Mach-O header parsing and final hashing using blocking `O_RDONLY | O_NOFOLLOW`, then closes in `finally`. A close rejection replaces a read failure or completed observation and leaves no retained cleanup owner. The outer catch also replaces any failure with cancellation if the signal has subsequently aborted. The final hash close has no post-close cancellation check. ### Reproduction NOT_ENOUGH_INFO: no historical caller failure or live Mach-O target reproduction is available. Inspected the three raw open/read/finally-close paths and the outer catch at the source revision below. Proposed controlled checks: real descriptor close rejection after IO failure; cancellation during the final digest close; regular pathname replaced by FIFO between enumeration and open. ### Expected behavior AGENTS.md and docs/tool-design.md#own-the-lifecycle require nonblocking regular-file admission, exact retained cleanup ownership, preserving primary failures and caller cancellation reasons, and observing cancellation after final awaited cleanup. All three readers should use the shared file owner rather than duplicate admission and finalization. ### Impact and scope Source-derived: all trace_dylib_resolution paths use these readers. A substituted FIFO can block a bundle magic probe or image/hash read; failed close can lose the primary outcome and retry capability; finalization cancellation can report success. Natural occurrence and native Windows behavior are unknown. ### REA version 6.5.0; base fe2a398dd9ab290ba6cb3411403d319cec8d07a2 with ongoing local audit changes. ### Runtime and platform Source analysis on macOS arm64; pinned Node24.18.0. Runtime reproduction not claimed. ### Target and artifact context Mach-O executable and bundle dyld path resolution; read-only files. ### Interface Shared provider used by CLI/MCP; source audit only at filing. ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence `src/artifacts/apple/DylibResolutionReader.ts`: startsWithMachoMagic, readImage and fileSha256 each own a raw descriptor with an unqualified finally-close. traceDylibResolution catch guesses cancellation from later signal state; fileSha256 returns through its final close. `src/artifacts/ArtifactProvider.ts` already owns an ArtifactResourceScope but does not pass it into dyld resolution. These are source-derived observations, not measured leak counts or runtime errors. ### Typed outcome or recovery expected Keep original IO failure and exact cancellation cause. Preserve completed observations separately from cleanup uncertainty; retain the exact failed descriptor for retry through provider close. Reject special files without waiting for a writer. ### Analysis or suspected cause Duplicated file admission/finalization instead of the shared nonblocking regular-file owner, plus downstream interpretation of current signal state. Proposed correction is one owning dyld file-access boundary using existing artifact resource and cleanup leases. ### Additional context Adjacent to #4483 (read-stream precedence) and #4475 (firmware descriptor lifetime); this independent dyld reader is not corrected by those changes. Verification results will be recorded separately after execution.
Author
Owner

@LuckVd commented on GitHub (Oct 16, 2026):

Hi, thanks for the report. We attempted a fix for this issue but could not reproduce it locally within our time budget (verify stage), so we are releasing our claim to avoid blocking others. Details: 未进入 pr/ci,未 push、未开 PR。Node 24.18.0/npm 11.16.0 下,npm run build、npm run lint、git diff --check 均通过;聚焦测试 34 passed、1 skipped。npm run check:fast 因新增测试中 blocked.ok 的 expect 断言不能收窄 Result,导致 blocked.error 在第181行 TS2339 而失败;错误位于本次新增文件,非基线失败。另,完成的 RegularFileCleanupFailure outcome 与 signal.reason 虽在内部 caus

<!-- gh-comment-id:6217803261 --> @LuckVd commented on GitHub (Oct 16, 2026): Hi, thanks for the report. We attempted a fix for this issue but could not reproduce it locally within our time budget (verify stage), so we are releasing our claim to avoid blocking others. Details: 未进入 pr/ci,未 push、未开 PR。Node 24.18.0/npm 11.16.0 下,npm run build、npm run lint、git diff --check 均通过;聚焦测试 34 passed、1 skipped。npm run check:fast 因新增测试中 blocked.ok 的 expect 断言不能收窄 Result,导致 blocked.error 在第181行 TS2339 而失败;错误位于本次新增文件,非基线失败。另,完成的 RegularFileCleanupFailure outcome 与 signal.reason 虽在内部 caus
Author
Owner

@morluto commented on GitHub (Oct 18, 2026):

Closing as fixed on main after reconciling this report with the landed owner/consumer changes.

  • d292c445e: fix(apple): share dylib read ownership and cancellation facts. Normalize dylib file access once at the admitted descriptor boundary. Preserve full file identity, physical read outcomes, cancellation provenance and cleanup retry through artifact analysis.

Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.

<!-- gh-comment-id:6256013922 --> @morluto commented on GitHub (Oct 18, 2026): <!-- rea-backlog-reconciliation-2026-10-19-4495 --> Closing as fixed on `main` after reconciling this report with the landed owner/consumer changes. - [d292c445e](https://github.com/morluto/rea/commit/d292c445ee4e9271906e444979f384c8f97008c9): fix(apple): share dylib read ownership and cancellation facts. Normalize dylib file access once at the admitted descriptor boundary. Preserve full file identity, physical read outcomes, cancellation provenance and cleanup retry through artifact analysis. Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.
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#1781
No description provided.