[GH-ISSUE #4845] [Bug] JADX Java readiness returns cancellation before owned probe cleanup #3010

Closed
opened 2026-10-31 00:34:48 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • Searched open and closed Java probe and JADX reports; related #4561 concerns Ghidra and #4844 concerns the later JADX bridge startup.
  • No credentials or private target data included.

Area

Provider or capability discovery

Observed behavior

At main 3ad1032b11, cancelling JADX Java readiness settles the inspection promise while the selected prerequisite child remains alive in its SIGTERM handler. No engine or APK target execution is involved.

Reproduction

Ran one controlled subprocess regression in tests/boundary/android/jadxConfiguration.test.ts on Node 24.18.0/macOS arm64. An authored Java launcher shim acknowledges SIGTERM and waits for a test-owned release file before exiting. After the acknowledgement and before release, inspectJadxAvailability has already rejected. The assertion expect(settled).toBe(false) fails with true. The fixture is released in finally and has its own watchdog. This is an authored launcher, not a real JVM failure.

Expected behavior

Readiness must join owned cancellation and final output collection, retain exact cleanup capabilities when closure cannot be confirmed, and let provider/doctor shutdown retry them. Complete invalid module observations must remain primary across late cancellation. Follow AGENTS.md ownership rules and docs/tool-design.md lifecycle guidance.

Impact and scope

Observed once at the production configuration boundary. Source consumers include JadxProvider admission/availability and the doctor adapter. Actual JVM incidents, frequency and native Windows/Linux behavior: NOT_ENOUGH_INFO.

REA version

6.5.0 source, 3ad1032b11

Runtime and platform

Node 24.18.0, macOS arm64. Authored Node prerequisite launcher only.

Target and artifact context

Tiny generated JAR inventory supplies prerequisites; no reverse-engineering target is launched.

Interface

Shared configuration boundary used by CLI/MCP.

Earliest failure stage

Setup or provider admission

Relevant output or evidence

Baseline regression: 1 failed, 12 skipped; settled is true while child SIGTERM acknowledgement exists and the release file does not. inspectJavaRuntime uses execFileOutput without owned command supervision. It and outer configuration catches consult current signal.aborted before interpreting producer failures.

Typed outcome or recovery expected

Owned bounded command completion, exact opaque cancellation reason, retained partial/final output, explicit unresolved cleanup and retry through the caller's durable resource scope.

Analysis or suspected cause

Node execFile abort can reject before process exit. The JADX prerequisite does not use the runOwnedCommand lifecycle already used by the Ghidra prerequisite. Simply changing a kill signal does not establish descendant/output completion or retained cleanup ownership.

Additional context

Proposed checks include cancellation during cleanup, escalation, inherited output, mixed cleanup results, retry, concurrent availability and provider shutdown. Real public CLI/MCP verification remains to be performed; no broad provider claim yet.

Originally created by @morluto on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4845 ### Before submitting - [x] Searched open and closed Java probe and JADX reports; related #4561 concerns Ghidra and #4844 concerns the later JADX bridge startup. - [x] No credentials or private target data included. ### Area Provider or capability discovery ### Observed behavior At main 3ad1032b11edea2dcb054e78f951cc43159ae83d, cancelling JADX Java readiness settles the inspection promise while the selected prerequisite child remains alive in its SIGTERM handler. No engine or APK target execution is involved. ### Reproduction Ran one controlled subprocess regression in tests/boundary/android/jadxConfiguration.test.ts on Node 24.18.0/macOS arm64. An authored Java launcher shim acknowledges SIGTERM and waits for a test-owned release file before exiting. After the acknowledgement and before release, inspectJadxAvailability has already rejected. The assertion `expect(settled).toBe(false)` fails with true. The fixture is released in finally and has its own watchdog. This is an authored launcher, not a real JVM failure. ### Expected behavior Readiness must join owned cancellation and final output collection, retain exact cleanup capabilities when closure cannot be confirmed, and let provider/doctor shutdown retry them. Complete invalid module observations must remain primary across late cancellation. Follow AGENTS.md ownership rules and docs/tool-design.md lifecycle guidance. ### Impact and scope Observed once at the production configuration boundary. Source consumers include JadxProvider admission/availability and the doctor adapter. Actual JVM incidents, frequency and native Windows/Linux behavior: NOT_ENOUGH_INFO. ### REA version 6.5.0 source, 3ad1032b11edea2dcb054e78f951cc43159ae83d ### Runtime and platform Node 24.18.0, macOS arm64. Authored Node prerequisite launcher only. ### Target and artifact context Tiny generated JAR inventory supplies prerequisites; no reverse-engineering target is launched. ### Interface Shared configuration boundary used by CLI/MCP. ### Earliest failure stage Setup or provider admission ### Relevant output or evidence Baseline regression: 1 failed, 12 skipped; `settled` is true while child SIGTERM acknowledgement exists and the release file does not. inspectJavaRuntime uses execFileOutput without owned command supervision. It and outer configuration catches consult current signal.aborted before interpreting producer failures. ### Typed outcome or recovery expected Owned bounded command completion, exact opaque cancellation reason, retained partial/final output, explicit unresolved cleanup and retry through the caller's durable resource scope. ### Analysis or suspected cause Node execFile abort can reject before process exit. The JADX prerequisite does not use the runOwnedCommand lifecycle already used by the Ghidra prerequisite. Simply changing a kill signal does not establish descendant/output completion or retained cleanup ownership. ### Additional context Proposed checks include cancellation during cleanup, escalation, inherited output, mixed cleanup results, retry, concurrent availability and provider shutdown. Real public CLI/MCP verification remains to be performed; no broad provider claim yet.
bsakaguchi 2026-10-31 00:34:48 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
Author
Owner

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

Fixed on main in 964decd989 and ceeff5a417.

JADX Java preflight now uses owned async command supervision and the caller's durable cleanup scope. Provider/doctor shutdown cancels and joins readiness, including final archive close. Complete module observations survive late cancellation and failed cleanup; exact opaque reasons, live resource labels and unknowns survive retries. Shared Ghidra cleanup adoption is reused. The probe uses its10s deadline and a1MiB combined output budget (the legacy execFile cap was per stream), and validates numeric Java facts without inventing termination attribution.

Validation: latest affected coverage223 passing tests across21files,1platformskip; static/typecheck/lint, docs and discovery1547files pass. The baseline3ad controlled cancellation settles while its child remains alive; the candidate joins cleanup. Tests cover inherited pipes, concurrent callers, provider shutdown, completed observations, failed cleanup, mixed helper peers and unknown labels. The foundation commit also builds/typechecks/lints independently. Two final source reviews clear.

Public verification:9CLI+9MCP inspections pass with real JADX0.7.1/JDK21 on the authored5classAPK. A controlled public doctor SIGINT leaves the selected Java's token-verified group empty; its exit1 rather than130 is tracked separately in #4848. Six additional completed MCP workflows preserve normalized results. Warm2repeat medians baseline/candidate: elapsed2.104/2.273s, reaped-familyCPU3.255/3.398s, sampled familyRSS845086720/860839936bytes, cl100k reply estimates9580/9621tokens. Small normal-path check only; no speedup/whole-agent token/true-cold claim. All6measuredroots are absent and no matching processes remain; measured runtime hashes match the commits.

Limitations: authored launcher controls do not establish actual JVM failure/OOM behavior; nativeWindows/Linux and failure-path costs remain unverified. Separate archive descriptor failure retention is tracked in #4846. Heavy profiling/stress remain stopped. Earlier failed harness attempts and corrected test oracles are retained locally; no runtime/provider claims rely on them.

<!-- gh-comment-id:6238206149 --> @morluto commented on GitHub (Oct 17, 2026): Fixed on main in 964decd989acfa84c4bfc3295362c4c46877fc20 and ceeff5a41788e47e5aee96a4baf191a6ce7fde4b. JADX Java preflight now uses owned async command supervision and the caller's durable cleanup scope. Provider/doctor shutdown cancels and joins readiness, including final archive close. Complete module observations survive late cancellation and failed cleanup; exact opaque reasons, live resource labels and unknowns survive retries. Shared Ghidra cleanup adoption is reused. The probe uses its10s deadline and a1MiB combined output budget (the legacy execFile cap was per stream), and validates numeric Java facts without inventing termination attribution. Validation: latest affected coverage223 passing tests across21files,1platformskip; static/typecheck/lint, docs and discovery1547files pass. The baseline3ad controlled cancellation settles while its child remains alive; the candidate joins cleanup. Tests cover inherited pipes, concurrent callers, provider shutdown, completed observations, failed cleanup, mixed helper peers and unknown labels. The foundation commit also builds/typechecks/lints independently. Two final source reviews clear. Public verification:9CLI+9MCP inspections pass with real JADX0.7.1/JDK21 on the authored5classAPK. A controlled public doctor SIGINT leaves the selected Java's token-verified group empty; its exit1 rather than130 is tracked separately in #4848. Six additional completed MCP workflows preserve normalized results. Warm2repeat medians baseline/candidate: elapsed2.104/2.273s, reaped-familyCPU3.255/3.398s, sampled familyRSS845086720/860839936bytes, cl100k reply estimates9580/9621tokens. Small normal-path check only; no speedup/whole-agent token/true-cold claim. All6measuredroots are absent and no matching processes remain; measured runtime hashes match the commits. Limitations: authored launcher controls do not establish actual JVM failure/OOM behavior; nativeWindows/Linux and failure-path costs remain unverified. Separate archive descriptor failure retention is tracked in #4846. Heavy profiling/stress remain stopped. Earlier failed harness attempts and corrected test oracles are retained locally; no runtime/provider claims rely on them.
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#3010
No description provided.