diff --git a/gateway/run.py b/gateway/run.py index ff82fe43582..897cb85f652 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -4338,12 +4338,20 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew f"while kill -0 {current_pid} 2>/dev/null; do sleep 0.2; done; " f"{cmd} gateway restart" ) + # Same marker scrub as the Windows watcher above: this watcher runs + # `hermes gateway restart` from outside the gateway, but it inherits + # _HERMES_GATEWAY=1 from us, and the CLI's self-restart loop guard + # refuses to run when that marker is set — silently (DEVNULL), so the + # gateway stops and never comes back. + watcher_env = os.environ.copy() + watcher_env.pop("_HERMES_GATEWAY", None) setsid_bin = shutil.which("setsid") if setsid_bin: subprocess.Popen( [setsid_bin, "bash", "-lc", shell_cmd], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + env=watcher_env, start_new_session=True, ) else: @@ -4351,6 +4359,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew ["bash", "-lc", shell_cmd], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + env=watcher_env, start_new_session=True, ) diff --git a/scripts/release.py b/scripts/release.py index 16b8bd7cdb8..ff4f4bc6da7 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -75,6 +75,7 @@ AUTHOR_MAP = { "129007007+HeLLGURD@users.noreply.github.com": "HeLLGURD", "290859878+synapsesx@users.noreply.github.com": "synapsesx", "dirtyren@users.noreply.github.com": "dirtyren", + "470766206@qq.com": "youjunxiaji", "mharris@parallel.ai": "NormallyGaussian", "roger@roger.local": "mollusk", "ted.malone@outlook.com": "temalo", diff --git a/tests/gateway/test_restart_drain.py b/tests/gateway/test_restart_drain.py index 32710fdb897..15b948a4f79 100644 --- a/tests/gateway/test_restart_drain.py +++ b/tests/gateway/test_restart_drain.py @@ -200,6 +200,7 @@ async def test_launch_detached_restart_command_uses_setsid(monkeypatch): monkeypatch.setattr(gateway_run.sys, "platform", "linux") monkeypatch.setattr(gateway_run, "_resolve_hermes_bin", lambda: ["/usr/bin/hermes"]) monkeypatch.setattr(gateway_run.os, "getpid", lambda: 321) + monkeypatch.setenv("_HERMES_GATEWAY", "1") monkeypatch.setattr(shutil, "which", lambda cmd: "/usr/bin/setsid" if cmd == "setsid" else None) def fake_popen(cmd, **kwargs): @@ -218,6 +219,9 @@ async def test_launch_detached_restart_command_uses_setsid(monkeypatch): assert kwargs["start_new_session"] is True assert kwargs["stdout"] is subprocess.DEVNULL assert kwargs["stderr"] is subprocess.DEVNULL + # The watcher must NOT inherit the gateway marker, or the CLI's + # self-restart loop guard refuses to run `hermes gateway restart`. + assert kwargs["env"].get("_HERMES_GATEWAY") is None def test_windows_gateway_venv_imports_add_site_packages(monkeypatch, tmp_path):