[GH-ISSUE #2459] Linux Hopper demo: dead owner leaves the singleton app wedging every later native op (exit 75, license-prompt advice, green doctor, no recovery) #820

Closed
opened 2026-10-15 18:28:45 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

  • I searched the open and closed issues for a related report (found #494, different symptom; PRs #1158/#1275/#1763 assume a live or cleanly-stopped owner).
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis / Hopper provider lifecycle (Linux demo).

Observed behavior

After the Linux demo Hopper application outlives its owning REA session (owner exits by design on MCP shutdown, or is SIGKILLed mid-session), every later native operation fails permanently:

  • rea analyze <any target> → provider_unavailable, failure_code: hopper_exited_during_startup, exit_code: 75, retryable: true, retry_action: "retry".
  • The remediation points at a UI/license prompt ("if Hopper showed a UI or license prompt, complete it in the runner user session, otherwise close stale Hopper sessions and retry"), but retrying provably never succeeds: identical failures at +11 s, +95 s, and +4.5 min.
  • rea doctor --provider hopper --json stays fully green during the wedge (launcher, version, and private-display checks all healthy).
  • No command can close or adopt the orphaned app: close_binary is MCP-session-scoped and there is no CLI close; recovery requires manually killing the orphaned helper/Hopper/Xvfb processes.

Controlled reproduction (all output verbatim captured; WSL2 Ubuntu 24.04, rea 6.4.0 CLI, Hopper 6.4.2 demo):

1. rea analyze /bin/true                 -> exit=0 (6201 ms)          # clean baseline
2. rea mcp (fifo-driven, pid A):
   initialize -> ok; tools/call open_binary {/bin/true} -> ok
   tools/call list_procedures -> ok
   ps: hopper-demo-x11.py ... ; /opt/hopper/bin/Hopper -l ELF ... (alive, lease held)
3. kill -9 A                             # orphan the owner only
4. rea analyze /usr/bin/uuidgen          -> exit=1, exit-75 failure   # +11 s
   rea analyze /usr/bin/uuidgen          -> exit=1, identical         # +95 s
   rea analyze /usr/bin/uuidgen          -> exit=1, identical         # +4.5 min
5. rea doctor --provider hopper          -> healthy: true             # during wedge
6. kill orphaned helper/Hopper/Xvfb manually
   rea analyze /usr/bin/uuidgen          -> exit=0 (10273 ms)         # control

The same wedge also occurs after a graceful MCP shutdown that used Hopper (the designed document-retention path), observed passively four times before the controlled cycle.

Expected behavior

docs/installation.md states "Closing the owning REA session releases this guard ... A later REA session can therefore open another document for the same target" (322-326) and "A competing CLI or MCP session receives the owning session ID before Hopper is launched" (340-347). With the app alive and the owner gone, sessions get neither the owning run ID nor a working launch nor an accurate diagnostic; they get a permanent wedge with license-prompt advice.

Root cause (read at main @ 37b7550ec)

  1. The app legitimately outlives its owner: src/main/shutdown.ts:39 hardcodes retainProviderDocuments: true; bridge/hopper_bridge.py:738-744 answers shutdown with document_retained: true; src/hopper/HopperCleanup.ts:81-94 leaves the external application running. SIGKILL reaches the same end-state.
  2. The lease models socket liveness only (src/hopper/HopperTargetLease.ts:135-138): stale detection (267-270) removes and rebinds the socket without checking whether a Hopper process from the dead owner still exists.
  3. The vendor demo forwards the new launch into the existing singleton, so the new child exits immediately; scripts/hopper-demo-x11.py:702-715 maps that to exit 75 hopper_exited_during_startup.
  4. src/domain/hopperStartupFailure.ts:32-36 projects exit 75 to the license-prompt remediation and retry_action: "retry".

Impact and scope

Every Linux user of the MCP path eventually hits this: any disconnect/crash/normal end of an agent session that opened a Hopper target leaves the singleton occupied, after which all native analysis (CLI and MCP) fails permanently with misleading guidance while doctor stays green. Manual ps + kill is the only recovery.

Possible fix direction (not prescriptive): when hopper_exited_during_startup occurs (or pre-launch), detect an existing Hopper application with no live lease owner (the vendor binary via process scan, or /tmp/rea-* ownership records with a dead parent pid) and raise the existing "already active" error shape naming the retained process and how to close it, with retry_action: "unknown" instead of "retry". A behavioral alternative would be not retaining the document at MCP shutdown for the headless Linux demo.

REA version

rea-agents 6.4.0 (npm); code points confirmed unchanged at main 37b7550ec.

Runtime and platform

WSL2 Ubuntu 24.04 x64, Node 24.20.0, Hopper 6.4.2 Linux demo at /opt/hopper/bin/Hopper with Xvfb.

Target and artifact context

Targets were ordinary system ELF binaries (/bin/true, /usr/bin/uuidgen); the wedge is target-independent.

Originally created by @Joshwong1908 on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2459 ### Before submitting - [x] I searched the open and closed issues for a related report (found #494, different symptom; PRs #1158/#1275/#1763 assume a live or cleanly-stopped owner). - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Native analysis / Hopper provider lifecycle (Linux demo). ### Observed behavior After the Linux demo Hopper application outlives its owning REA session (owner exits by design on MCP shutdown, or is SIGKILLed mid-session), every later native operation fails permanently: - `rea analyze <any target>` → `provider_unavailable`, `failure_code: hopper_exited_during_startup`, `exit_code: 75`, `retryable: true`, `retry_action: "retry"`. - The remediation points at a UI/license prompt ("if Hopper showed a UI or license prompt, complete it in the runner user session, otherwise close stale Hopper sessions and retry"), but retrying provably never succeeds: identical failures at +11 s, +95 s, and +4.5 min. - `rea doctor --provider hopper --json` stays fully green during the wedge (launcher, version, and private-display checks all healthy). - No command can close or adopt the orphaned app: `close_binary` is MCP-session-scoped and there is no CLI close; recovery requires manually killing the orphaned helper/Hopper/Xvfb processes. Controlled reproduction (all output verbatim captured; WSL2 Ubuntu 24.04, rea 6.4.0 CLI, Hopper 6.4.2 demo): ``` 1. rea analyze /bin/true -> exit=0 (6201 ms) # clean baseline 2. rea mcp (fifo-driven, pid A): initialize -> ok; tools/call open_binary {/bin/true} -> ok tools/call list_procedures -> ok ps: hopper-demo-x11.py ... ; /opt/hopper/bin/Hopper -l ELF ... (alive, lease held) 3. kill -9 A # orphan the owner only 4. rea analyze /usr/bin/uuidgen -> exit=1, exit-75 failure # +11 s rea analyze /usr/bin/uuidgen -> exit=1, identical # +95 s rea analyze /usr/bin/uuidgen -> exit=1, identical # +4.5 min 5. rea doctor --provider hopper -> healthy: true # during wedge 6. kill orphaned helper/Hopper/Xvfb manually rea analyze /usr/bin/uuidgen -> exit=0 (10273 ms) # control ``` The same wedge also occurs after a graceful MCP shutdown that used Hopper (the designed document-retention path), observed passively four times before the controlled cycle. ### Expected behavior docs/installation.md states "Closing the owning REA session releases this guard ... A later REA session can therefore open another document for the same target" (322-326) and "A competing CLI or MCP session receives the owning session ID before Hopper is launched" (340-347). With the app alive and the owner gone, sessions get neither the owning run ID nor a working launch nor an accurate diagnostic; they get a permanent wedge with license-prompt advice. ### Root cause (read at main @ 37b7550ec) 1. The app legitimately outlives its owner: `src/main/shutdown.ts:39` hardcodes `retainProviderDocuments: true`; `bridge/hopper_bridge.py:738-744` answers `shutdown` with `document_retained: true`; `src/hopper/HopperCleanup.ts:81-94` leaves the external application running. SIGKILL reaches the same end-state. 2. The lease models socket liveness only (`src/hopper/HopperTargetLease.ts:135-138`): stale detection (267-270) removes and rebinds the socket without checking whether a Hopper process from the dead owner still exists. 3. The vendor demo forwards the new launch into the existing singleton, so the new child exits immediately; `scripts/hopper-demo-x11.py:702-715` maps that to exit 75 `hopper_exited_during_startup`. 4. `src/domain/hopperStartupFailure.ts:32-36` projects exit 75 to the license-prompt remediation and `retry_action: "retry"`. ### Impact and scope Every Linux user of the MCP path eventually hits this: any disconnect/crash/normal end of an agent session that opened a Hopper target leaves the singleton occupied, after which all native analysis (CLI and MCP) fails permanently with misleading guidance while doctor stays green. Manual `ps` + `kill` is the only recovery. Possible fix direction (not prescriptive): when `hopper_exited_during_startup` occurs (or pre-launch), detect an existing Hopper application with no live lease owner (the vendor binary via process scan, or `/tmp/rea-*` ownership records with a dead parent pid) and raise the existing "already active" error shape naming the retained process and how to close it, with `retry_action: "unknown"` instead of "retry". A behavioral alternative would be not retaining the document at MCP shutdown for the headless Linux demo. ### REA version rea-agents 6.4.0 (npm); code points confirmed unchanged at main 37b7550ec. ### Runtime and platform WSL2 Ubuntu 24.04 x64, Node 24.20.0, Hopper 6.4.2 Linux demo at /opt/hopper/bin/Hopper with Xvfb. ### Target and artifact context Targets were ordinary system ELF binaries (/bin/true, /usr/bin/uuidgen); the wedge is target-independent.
bsakaguchi 2026-10-15 18:28:45 +00:00
  • closed this issue
  • added the
    bug
    label
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#820
No description provided.