Merge pull request #178 from nesquena/fix/streaming-env-lock-deadlock

fix: resolve _ENV_LOCK deadlock that blocks chat after first message
This commit is contained in:
Nathan Esquenazi
2026-04-08 07:26:53 -07:00
committed by GitHub
3 changed files with 26 additions and 12 deletions

View File

@@ -5,6 +5,17 @@
---
## [v0.39.1] — 2026-04-08
### Bug Fixes
- **_ENV_LOCK deadlock resolved.** The environment variable lock was held for
the entire duration of agent execution (including all tool calls and streaming),
blocking all concurrent requests. Now the lock is acquired only for the brief
env variable read/write operations, released before the agent runs, and
re-acquired in the finally block for restoration.
---
## [v0.39.0] — 2026-04-08
### Security (12 fixes — PR #171 by @betamod, reviewed by @nesquena-hermes)

View File

@@ -107,6 +107,9 @@ def _run_agent_streaming(session_id, msg_text, model, workspace, stream_id, atta
HERMES_HOME=_profile_home,
)
# Still set process-level env as fallback for tools that bypass thread-local
# Acquire lock only for the env mutation, then release before the agent runs.
# The finally block re-acquires to restore — keeping critical sections short
# and preventing a deadlock where the restore would re-enter the same lock.
with _ENV_LOCK:
old_cwd = os.environ.get('TERMINAL_CWD')
old_exec_ask = os.environ.get('HERMES_EXEC_ASK')
@@ -117,7 +120,7 @@ def _run_agent_streaming(session_id, msg_text, model, workspace, stream_id, atta
os.environ['HERMES_SESSION_KEY'] = session_id
if _profile_home:
os.environ['HERMES_HOME'] = _profile_home
# Lock released — agent runs without holding it
try:
def on_token(text):
if text is None:

View File

@@ -14,7 +14,7 @@
<body>
<div class="layout">
<aside class="sidebar">
<div class="sidebar-header"><div class="logo">H</div><div><h1 style="margin:0;font-size:15px;font-weight:700;letter-spacing:-.01em">Hermes</h1><div style="font-size:10px;color:var(--muted);opacity:.8;margin-top:1px">v0.39.0</div></div></div>
<div class="sidebar-header"><div class="logo">H</div><div><h1 style="margin:0;font-size:15px;font-weight:700;letter-spacing:-.01em">Hermes</h1><div style="font-size:10px;color:var(--muted);opacity:.8;margin-top:1px">v0.39.1</div></div></div>
<div class="sidebar-nav">
<button class="nav-tab active" data-panel="chat" data-label="Chat" onclick="switchPanel('chat')" title="Chat">&#128172;</button>
<button class="nav-tab" data-panel="tasks" data-label="Tasks" onclick="switchPanel('tasks')" title="Tasks">&#128197;</button>