Skip to content

fix(hermes): defer sanitizer patch out of plugin discovery lock - #60

Open
prismatic7 wants to merge 1 commit into
EfficientContext:mainfrom
prismatic7:fix/hermes-tui-startup-deadlock
Open

fix(hermes): defer sanitizer patch out of plugin discovery lock#60
prismatic7 wants to merge 1 commit into
EfficientContext:mainfrom
prismatic7:fix/hermes-tui-startup-deadlock

Conversation

@prismatic7

Copy link
Copy Markdown

Problem

First launch of the Hermes TUI over an interactive SSH session stalls: the UI renders but nothing responds. Ctrl+C and relaunch works. This is an ABBA deadlock between two threads at TUI startup:

  • Discovery thread (tui-mcp-discovery): holds _discovery_lock (in Hermes' hermes_cli/plugins.py) → loads plugins → contextpilot.register()_patch_hermes_sanitizer()import run_agentblocks on the Python import lock
  • Agent build thread (_build): holds the import lock (importing run_agent) → module-level model_tools.discover_plugins()blocks on _discovery_lock

Each thread holds one lock and waits on the other → deadlock → the TUI's run_after_agent_ready waits forever on ready.wait().

Fix

Remove the eager _patch_hermes_sanitizer() call from register(). The patch is already applied safely in ContextPilotEngine.on_session_start() (line 706), which Hermes invokes at agent init — after the agent is built, so run_agent is already imported and there is no lock contention. The eager call in register() is redundant and is the only path that imports run_agent while the discovery lock is held.

Verification

  • register() no longer imports run_agent; the patch still installs on the first session start.
  • Syntax-checked; no other eager _patch_hermes_sanitizer() call sites remain.
  • Reproduced the stall on Hermes TUI (first launch over SSH), confirmed the deadlock via thread dump, and confirmed this is the only plugin importing run_agent during discovery.

register() called _patch_hermes_sanitizer() eagerly, which imports
run_agent while PluginManager holds _discovery_lock. The TUI gateway
builds the agent in a parallel thread that imports run_agent and then
calls model_tools.discover_plugins() under the same lock — an ABBA
deadlock that stalls first TUI launch over SSH (renders, but nothing
responds; ctrl+c and relaunch works).

The patch is already applied safely in on_session_start(), which fires
after the agent is built, so the eager call in register() is redundant.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant