From 2a2e6ee2a4bea45a9978deae81a3dce366198085 Mon Sep 17 00:00:00 2001 From: RelaxJonh <92573950+RelaxJonh@users.noreply.github.com> Date: Sun, 2 Aug 2026 23:13:12 +0530 Subject: [PATCH] fix(gateway): reap orphans on stop_profile_gateway (#75936) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stop_profile_gateway() only killed the single PID recorded in the pid file. On repeated restarts, the new process overwrites the pid file before the old one exits, making older gateway instances invisible to subsequent stops. Each restart stacked another orphan — observed as N threads and N replies per Discord message. After killing the recorded PID, also call _reap_unsupervised_gateway_orphans() to sweep any remaining gateway processes for this profile. The reap function already handles the no-systemd guard and SIGTERM+SIGKILL escalation. Fixes #75936 --- hermes_cli/gateway.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hermes_cli/gateway.py b/hermes_cli/gateway.py index 7d30531cf8dfc..aea24118a8430 100644 --- a/hermes_cli/gateway.py +++ b/hermes_cli/gateway.py @@ -1583,6 +1583,12 @@ def stop_profile_gateway() -> bool: a live orphan still holds the webhook port. In that case fall back to the orphan-aware process scan so the replacement reaps the prior instance instead of stacking a duplicate on the same port (#51325). + + Even when the pid file is valid and points to the current gateway, older + orphans may linger from prior restarts that overwrote the pid file before + the old process exited. After killing the recorded PID, also sweep for + any remaining orphans so each restart produces at most one live gateway + (#75936). """ try: from gateway.status import get_running_pid, remove_pid_file @@ -1620,6 +1626,14 @@ def stop_profile_gateway() -> bool: if get_running_pid() is None: remove_pid_file() + + # Also reap any orphans from prior restarts whose PIDs were overwritten + # in the pid file before they exited (#75936). + try: + _reap_unsupervised_gateway_orphans() + except Exception: + pass + return True