[GH-ISSUE #6370] [Bug] Queued GDB commands run after their session starts closing #3827

Closed
opened 2026-10-31 00:44:26 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

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

Area

Process capture or runtime observation

Observed behavior

A gdb_console command queued behind an active command still runs after close_gdb_session or manager shutdown (closeAll()) has started for that session. A second close_gdb_session queued behind the first repeats the exit and stop sequence.

GdbSessionManager.execute() checks that the session is open only when the call arrives. When its queued turn starts, it rechecks only session.exited and session.protocolError. The GDB child's exit event can arrive after the stop result, so neither is set yet when the queued command's turn comes.

Reproduction

Ran on Linux (WSL Ubuntu, Node 24.18.0) with the fake GDB spawner used by tests/boundary/providers/GdbSessionManagerCoverage.test.ts:

  1. Start a session and send a command that the fake holds open.
  2. Queue run on the same session, then call closeAll() (or close(session_id)).
  3. Release the held command.
  4. On upstream/main, run is sent to the closing GDB. If a duplicate close(session_id) is queued in step 2 instead, it sends -gdb-exit and stops the process a second time.

Expected behavior

Once a close has started, queued commands fail with the same "GDB session is unavailable or closed." input error that a new command gets. A queued duplicate close fails without repeating cleanup.

Impact and scope

This affects agents that issue gdb_console calls while close_gdb_session or server shutdown is in progress. A queued run or continue can start or resume the inferior while the session is being torn down. Single, sequential calls are not affected.

REA version

6.7.0, revision 86655eac6

Runtime and platform

Linux (WSL Ubuntu), Node 24.18.0

Target and artifact context

No target binary; fake GDB spawner.

Interface

MCP

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

src/gdb/GdbSessionManager.ts, execute() inside #serialize:

if (session.exited || session.protocolError !== undefined)
  return err(new AnalysisInputError("gdb_console"));

close() inside #serialize does not check whether an earlier close already removed the session.

Typed outcome or recovery expected

The existing AnalysisInputError for gdb_console and close_gdb_session.

Analysis or suspected cause

When the queued turn starts, it does not repeat the entry checks (#closing and session registration), so it depends on the exit event having already been observed.

Additional context

Fixed by #6369.

Originally created by @Adolanium on GitHub (Oct 22, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6370 ### 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 Process capture or runtime observation ### Observed behavior A `gdb_console` command queued behind an active command still runs after `close_gdb_session` or manager shutdown (`closeAll()`) has started for that session. A second `close_gdb_session` queued behind the first repeats the exit and stop sequence. `GdbSessionManager.execute()` checks that the session is open only when the call arrives. When its queued turn starts, it rechecks only `session.exited` and `session.protocolError`. The GDB child's exit event can arrive after the stop result, so neither is set yet when the queued command's turn comes. ### Reproduction Ran on Linux (WSL Ubuntu, Node 24.18.0) with the fake GDB spawner used by `tests/boundary/providers/GdbSessionManagerCoverage.test.ts`: 1. Start a session and send a command that the fake holds open. 2. Queue `run` on the same session, then call `closeAll()` (or `close(session_id)`). 3. Release the held command. 4. On upstream/main, `run` is sent to the closing GDB. If a duplicate `close(session_id)` is queued in step 2 instead, it sends `-gdb-exit` and stops the process a second time. ### Expected behavior Once a close has started, queued commands fail with the same "GDB session is unavailable or closed." input error that a new command gets. A queued duplicate close fails without repeating cleanup. ### Impact and scope This affects agents that issue `gdb_console` calls while `close_gdb_session` or server shutdown is in progress. A queued `run` or `continue` can start or resume the inferior while the session is being torn down. Single, sequential calls are not affected. ### REA version 6.7.0, revision `86655eac6` ### Runtime and platform Linux (WSL Ubuntu), Node 24.18.0 ### Target and artifact context No target binary; fake GDB spawner. ### Interface MCP ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence `src/gdb/GdbSessionManager.ts`, `execute()` inside `#serialize`: ```ts if (session.exited || session.protocolError !== undefined) return err(new AnalysisInputError("gdb_console")); ``` `close()` inside `#serialize` does not check whether an earlier close already removed the session. ### Typed outcome or recovery expected The existing `AnalysisInputError` for `gdb_console` and `close_gdb_session`. ### Analysis or suspected cause When the queued turn starts, it does not repeat the entry checks (`#closing` and session registration), so it depends on the exit event having already been observed. ### Additional context Fixed by #6369.
Author
Owner

@Adolanium commented on GitHub (Oct 23, 2026):

Fixed on main by #6411 (fix(lifecycle): reject session work once close has started): a queued GDB console command or a duplicate close now fails as unavailable once its turn finds the session closing or gone. Closing; #6369 is closed as superseded.

<!-- gh-comment-id:6359434005 --> @Adolanium commented on GitHub (Oct 23, 2026): Fixed on main by #6411 (`fix(lifecycle): reject session work once close has started`): a queued GDB console command or a duplicate close now fails as unavailable once its turn finds the session closing or gone. Closing; #6369 is closed as superseded.
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#3827
No description provided.