Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions hermes_cli/gateway_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ def _exec_schtasks(args: list[str]) -> tuple[int, str, str]:
[schtasks, *args],
capture_output=True,
text=True,
# schtasks emits text in the console's localized code page (e.g.
# cp936/GBK on Chinese Windows). When the ambient locale resolves
# to UTF-8 — common under git-bash/MSYS — the default strict decode
# raises UnicodeDecodeError inside subprocess's reader thread and
# spams a traceback even though the command succeeded (issue
# #34083). Decode defensively, matching find_gateway_pids() in
# gateway.py. The ASCII keys we parse (status, last run result)
# survive; only localized free-text becomes U+FFFD.
encoding="utf-8",
errors="replace",
timeout=_SCHTASKS_TIMEOUT_S,
# CREATE_NO_WINDOW avoids a flashing console window when the CLI
# is itself hosted in a TUI. See tools/browser_tool.py for the
Expand Down
33 changes: 32 additions & 1 deletion tests/hermes_cli/test_gateway_windows.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Tests for hermes_cli.gateway_windows."""

from pathlib import Path
from types import SimpleNamespace

import pytest

Expand Down Expand Up @@ -698,4 +699,34 @@ def fake_write(target_pid):
monkeypatch.setattr(status_mod, "_pid_exists", lambda check_pid: False)

# Returns True because _pid_exists immediately says "gone".
assert gateway_windows._drain_gateway_pid(pid, drain_timeout=5.0) is True
assert gateway_windows._drain_gateway_pid(pid, drain_timeout=5.0) is True


def test_exec_schtasks_decodes_defensively(monkeypatch):
"""schtasks output must decode without raising on non-UTF-8 console bytes.

On Chinese Windows the schtasks code page is cp936/GBK; under a UTF-8
ambient locale (git-bash/MSYS) the default strict decode raises
UnicodeDecodeError inside subprocess's reader thread, spamming a
traceback on an otherwise-successful ``hermes gateway status`` (#34083).
Pin the decode to errors="replace" so the call stays quiet.
"""
captured = {}

def fake_run(cmd, **kwargs):
captured.update(kwargs)
return SimpleNamespace(returncode=0, stdout="Status: Running", stderr="")

monkeypatch.setattr(gateway_windows, "_assert_windows", lambda: None)
monkeypatch.setattr(
gateway_windows.shutil, "which",
lambda name: r"C:\Windows\System32\schtasks.exe",
)
monkeypatch.setattr(gateway_windows.subprocess, "run", fake_run)

code, out, err = gateway_windows._exec_schtasks(["/Query", "/TN", "Hermes_Gateway"])

assert code == 0
assert out == "Status: Running"
assert captured.get("encoding") == "utf-8"
assert captured.get("errors") == "replace"
Loading