mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-27 17:58:07 +00:00
fix(gateway): survive faulthandler.enable() when sys.stderr is None
faulthandler.enable() writes to sys.stderr by default, and raises
RuntimeError('sys.stderr is None') when the gateway is launched
without an attached console — e.g. via the Windows Startup VBS shim,
pythonw.exe, a detached service, or any parent that redirects stderr
to DEVNULL. Because this happens on the very first line of
GatewayRunner.start(), the whole gateway used to die at startup and
every configured platform adapter (Discord bot, Telegram, Slack, …)
would silently show offline until the user manually re-ran
'hermes gateway run --replace' from a real terminal.
Wrap the call and fall back to a log-file file descriptor
(logs/gateway_faulthandler.log) when stderr is unavailable, so
fatal-error stack dumps still land somewhere useful. If even the
fallback fails we log-and-continue rather than kill the gateway.
Repro traceback (from a real user's gateway-exit-diag.log, launched
via the Startup VBS with stdin_is_tty=false):
File "gateway/run.py", line 7821, in start
faulthandler.enable()
RuntimeError: sys.stderr is None
This commit is contained in:
parent
b792bd0529
commit
3ec5fb076e
1 changed files with 18 additions and 4 deletions
|
|
@ -7823,10 +7823,24 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
|||
Returns True if at least one adapter connected successfully.
|
||||
"""
|
||||
logger.info("Starting Hermes Gateway...")
|
||||
# Enable faulthandler at gateway start so that SIGUSR2 (or an
|
||||
# internal watchdog) can dump all thread and task stacks to stderr
|
||||
# for post-mortem diagnosis of event-loop freezes (#70344).
|
||||
faulthandler.enable()
|
||||
# Enable faulthandler for stack dumps on freezes/crashes (#70344).
|
||||
# Falls back to a log file when sys.stderr is None (Windows VBS /
|
||||
# pythonw / detached service) — otherwise the gateway would die
|
||||
# here and take every adapter offline. See #71671.
|
||||
try:
|
||||
faulthandler.enable()
|
||||
except (RuntimeError, ValueError, OSError):
|
||||
try:
|
||||
_fh_log_dir = getattr(self.config, "log_dir", None) or os.path.join(
|
||||
os.environ.get("HERMES_HOME", str(Path.home() / ".hermes")),
|
||||
"logs",
|
||||
)
|
||||
os.makedirs(_fh_log_dir, exist_ok=True)
|
||||
_fh_enable_path = os.path.join(_fh_log_dir, "gateway_faulthandler.log")
|
||||
_fh_enable_file = open(_fh_enable_path, "a", encoding="utf-8")
|
||||
faulthandler.enable(file=_fh_enable_file, all_threads=True)
|
||||
except Exception:
|
||||
logger.debug("faulthandler.enable() unavailable", exc_info=True)
|
||||
# Also dump stacks to a rotating file for off-line analysis when
|
||||
# the gateway is running under a service manager that doesn't
|
||||
# capture stderr.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue