[GH-ISSUE #4289] [Bug] Ghidra request queue discards lifecycle ping deadlines #1693

Closed
opened 2026-10-16 21:09:09 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

Ghidra's request queue discards timeoutMs. A real Ghidra 12.1.4 verifier run failed its expired-ping check: client.ping({ timeoutMs: 0 }) did not return the expected timeout. A reduced queue regression failed before the fix because the executor received no timeout and returned success.

Reproduction

  1. On the PR #4274 branch at 54eeb11b2d31bc2492b2ae9faebeecc17994ccd3, build with Node 24.18.0 using npm run build:cached.
  2. With the existing Ghidra 12.1.4 and JDK21 installations selected through GHIDRA_INSTALL_DIR and JAVA_HOME, run node scripts/verify-real-ghidra.mjs.
  3. Observe Error: Ghidra expired ping deadline drifted from verifyRequestCancellationAndTimeout.

The native verifier was run once for this report. The queue failure was also reproduced in a focused test; frequency outside these controls is unknown.

Expected behavior

Every admitted request retains its complete GhidraRequestOptions, including its internal lifecycle deadline. A zero-deadline ping returns typed timeout; a disconnected session's bounded health probe settles so recovery can run. Ordinary analysis requests retain their existing absence of a fixed deadline.

Impact and scope

Observed in the native verifier and reduced request-queue control on macOS arm64. Source-derived impact: lifecycle health probes can wait beyond their requested deadline and delay reconnect decisions. Windows/Linux frequency and other providers are unverified.

REA version

REA 6.5.0 source branch for PR #4274; 54eeb11b2d31bc2492b2ae9faebeecc17994ccd3.

Runtime and platform

Node 24.18.0; macOS arm64; Ghidra 12.1.4; JDK21.

Target and artifact context

Repository-owned host-native Mach-O arm64 inventory fixture; controlled Unix-socket bridge fixtures for MCP recovery.

Interface

Other: Ghidra client API and MCP session recovery.

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

Native run: Error: Ghidra expired ping deadline drifted at scripts/verify-real-ghidra-function.mjs:409.

Reduced queue control: queue.run("ping", {}, { timeoutMs: 0 }) reached the executor without timeoutMs; the expected timeout assertion received { ok: true, value: null }.

Source: src/ghidra/GhidraRequestQueue.ts stores only signal in QueuedRequest, then reconstructs executor options from that field. src/ghidra/GhidraClientTypes.ts also declares timeoutMs as part of the accepted options.

Typed outcome or recovery expected

Retain the typed timeout and allow bounded session health/reconnect handling to continue.

Analysis or suspected cause

Confirmed producing boundary: the queue projects the options down to one field instead of preserving the accepted options object. Fix the queued representation and test deadline propagation through both queue and MCP recovery consumers.

Additional context

Related audit: #4227. Fixed by 6156421c3 in #4274; merge is pending. The Node 24 queue/client/MCP recovery selection passed 56/56 after the fix. A fresh real Ghidra 12.1.4/JDK21 host-native run then passed 373 CLI/stdio MCP calls and 52 expected refusals, with complete owned cleanup. Related startup-cancellation work #3983 has a different trigger. Two MCP reconnect checks also exposed an independent fixture timing issue: their one-second polling budget raced the bounded diagnostic drain. Those tests now await a single ping after the existing disconnect acknowledgement; they do not establish that deadline loss caused their original failures. Last known good revision: NOT_ENOUGH_INFO; not bisected.

Originally created by @morluto on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4289 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior Ghidra's request queue discards `timeoutMs`. A real Ghidra 12.1.4 verifier run failed its expired-ping check: `client.ping({ timeoutMs: 0 })` did not return the expected timeout. A reduced queue regression failed before the fix because the executor received no timeout and returned success. ### Reproduction 1. On the PR #4274 branch at `54eeb11b2d31bc2492b2ae9faebeecc17994ccd3`, build with Node 24.18.0 using `npm run build:cached`. 2. With the existing Ghidra 12.1.4 and JDK21 installations selected through `GHIDRA_INSTALL_DIR` and `JAVA_HOME`, run `node scripts/verify-real-ghidra.mjs`. 3. Observe `Error: Ghidra expired ping deadline drifted` from `verifyRequestCancellationAndTimeout`. The native verifier was run once for this report. The queue failure was also reproduced in a focused test; frequency outside these controls is unknown. ### Expected behavior Every admitted request retains its complete `GhidraRequestOptions`, including its internal lifecycle deadline. A zero-deadline ping returns typed `timeout`; a disconnected session's bounded health probe settles so recovery can run. Ordinary analysis requests retain their existing absence of a fixed deadline. ### Impact and scope Observed in the native verifier and reduced request-queue control on macOS arm64. Source-derived impact: lifecycle health probes can wait beyond their requested deadline and delay reconnect decisions. Windows/Linux frequency and other providers are unverified. ### REA version REA 6.5.0 source branch for PR #4274; `54eeb11b2d31bc2492b2ae9faebeecc17994ccd3`. ### Runtime and platform Node 24.18.0; macOS arm64; Ghidra 12.1.4; JDK21. ### Target and artifact context Repository-owned host-native Mach-O arm64 inventory fixture; controlled Unix-socket bridge fixtures for MCP recovery. ### Interface Other: Ghidra client API and MCP session recovery. ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence Native run: `Error: Ghidra expired ping deadline drifted` at `scripts/verify-real-ghidra-function.mjs:409`. Reduced queue control: `queue.run("ping", {}, { timeoutMs: 0 })` reached the executor without `timeoutMs`; the expected timeout assertion received `{ ok: true, value: null }`. Source: `src/ghidra/GhidraRequestQueue.ts` stores only `signal` in `QueuedRequest`, then reconstructs executor options from that field. `src/ghidra/GhidraClientTypes.ts` also declares `timeoutMs` as part of the accepted options. ### Typed outcome or recovery expected Retain the typed timeout and allow bounded session health/reconnect handling to continue. ### Analysis or suspected cause Confirmed producing boundary: the queue projects the options down to one field instead of preserving the accepted options object. Fix the queued representation and test deadline propagation through both queue and MCP recovery consumers. ### Additional context Related audit: #4227. Fixed by `6156421c3` in #4274; merge is pending. The Node 24 queue/client/MCP recovery selection passed 56/56 after the fix. A fresh real Ghidra 12.1.4/JDK21 host-native run then passed 373 CLI/stdio MCP calls and 52 expected refusals, with complete owned cleanup. Related startup-cancellation work #3983 has a different trigger. Two MCP reconnect checks also exposed an independent fixture timing issue: their one-second polling budget raced the bounded diagnostic drain. Those tests now await a single ping after the existing disconnect acknowledgement; they do not establish that deadline loss caused their original failures. Last known good revision: NOT_ENOUGH_INFO; not bisected.
bsakaguchi 2026-10-16 21:09:09 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
Author
Owner

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

Fixed on main in 5f0d18a53. The Ghidra FIFO now preserves the complete request options, including lifecycle ping deadlines.

Queue, expired-ping and MCP recovery regressions passed using controlled child bridges; Ghidra was not rerun for this main revision.

Hosted main CI is still pending; this closure is based on the implemented fix and the scoped regression evidence.

<!-- gh-comment-id:6206000416 --> @morluto commented on GitHub (Oct 16, 2026): Fixed on `main` in [5f0d18a53](https://github.com/morluto/rea/commit/5f0d18a534bbe7656a5b0981deb145bdbbb11ecb). The Ghidra FIFO now preserves the complete request options, including lifecycle ping deadlines. Queue, expired-ping and MCP recovery regressions passed using controlled child bridges; Ghidra was not rerun for this main revision. Hosted main CI is still pending; this closure is based on the implemented fix and the scoped regression evidence.
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#1693
No description provided.