Skip to content

fix(web-server): absorb _warm_gateway_module import before lifespan yield (#73083) - #73291

Closed
JonthanaHanh wants to merge 1 commit into
NousResearch:mainfrom
JonthanaHanh:fix/desktop-gil-stall-warm-gateway
Closed

fix(web-server): absorb _warm_gateway_module import before lifespan yield (#73083)#73291
JonthanaHanh wants to merge 1 commit into
NousResearch:mainfrom
JonthanaHanh:fix/desktop-gil-stall-warm-gateway

Conversation

@JonthanaHanh

Copy link
Copy Markdown
Contributor

Summary

On Windows + Python 3.11, the _warm_gateway_module() call in hermes_cli/web_server.py uses run_in_executor to import hermes_cli.gateway in a background thread. The intent was to avoid blocking the event loop during .pyc compilation and Defender real-time scans.

However, the heavy .pyc file reads do not release the GIL, so the event loop still freezes for 15–22 seconds. The Desktop Electron app's 10-second WebSocket ready-probe times out during this stall, causing a "Could not connect to Hermes gateway" error on startup.

Fix

Move _warm_gateway_module() from run_in_executor to a synchronous call before the lifespan yield. The GIL block is now absorbed during backend initialisation — before the server socket accepts probes — so the Desktop's probe timeout is never triggered.

Changes

  • hermes_cli/web_server.py: Replace asyncio.get_event_loop().run_in_executor(None, _warm_gateway_module) with _warm_gateway_module(), update comment to explain the GIL-related rationale.

Test Plan

  • Desktop on Windows: startup no longer shows "Could not connect" error
  • CLI hermes dashboard still works (the warm import is simply synchronous now)
  • No regressions in existing tests

Fixes #73083

…ield (NousResearch#73083)

On Windows + Python 3.11 the gateway import triggers heavy .pyc
compilation and Defender real-time scans that do not release the GIL.
Running in run_in_executor still froze the event loop for 15-22 s,
causing the Desktop's 10-second WebSocket ready-probe to time out.

Move the call from the executor to a synchronous invocation before the
lifespan yield, so the GIL block is absorbed during backend
initialisation — before the server socket accepts probes.

Fixes NousResearch#73083
@alt-glitch alt-glitch added type/perf Performance improvement or optimization P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/desktop Electron desktop app (apps/desktop/*) platform/windows Native Windows-specific behavior or breakage sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages needs-decision Awaiting maintainer decision before any implementation labels Jul 28, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #73083 documents the cold-start failure. Open warmup variants #60807 and #61895 use different readiness/import timing; this synchronous-before-yield approach needs comparison before selection.

kshitijk4poor added a commit to kshitijk4poor/hermes-agent that referenced this pull request Jul 29, 2026
…#73083)

The old test asserted _warm_gateway_module was fire-and-forget (startup
completes in << SLOW_SECONDS). PR NousResearch#73291 intentionally reversed this:
the import now runs synchronously before the lifespan yield because
run_in_executor didn't release the GIL on Windows + Python 3.11.
Updated the test to assert startup blocks for >= SLOW_SECONDS.
kshitijk4poor added a commit that referenced this pull request Jul 29, 2026
The old test asserted _warm_gateway_module was fire-and-forget (startup
completes in << SLOW_SECONDS). PR #73291 intentionally reversed this:
the import now runs synchronously before the lifespan yield because
run_in_executor didn't release the GIL on Windows + Python 3.11.
Updated the test to assert startup blocks for >= SLOW_SECONDS.
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Merged via #73907 — your sync warmup fix was salvaged with authorship preserved. Thanks for the contribution!

randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…#73083)

The old test asserted _warm_gateway_module was fire-and-forget (startup
completes in << SLOW_SECONDS). PR NousResearch#73291 intentionally reversed this:
the import now runs synchronously before the lifespan yield because
run_in_executor didn't release the GIL on Windows + Python 3.11.
Updated the test to assert startup blocks for >= SLOW_SECONDS.
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
…#73083)

The old test asserted _warm_gateway_module was fire-and-forget (startup
completes in << SLOW_SECONDS). PR NousResearch#73291 intentionally reversed this:
the import now runs synchronously before the lifespan yield because
run_in_executor didn't release the GIL on Windows + Python 3.11.
Updated the test to assert startup blocks for >= SLOW_SECONDS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/desktop Electron desktop app (apps/desktop/*) needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists platform/windows Native Windows-specific behavior or breakage sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows type/perf Performance improvement or optimization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desktop startup fails with GIL stall on Windows — _warm_gateway_module() import blocks event loop 15-22s

3 participants