Skip to content

[Bug]: hermes gateway restart --all leaves launchd service unloaded on macOS if interrupted #28632

@JiehoonKwak

Description

@JiehoonKwak

Bug Description

On macOS, hermes gateway restart --all is non-atomic. It runs launchctl bootout (which unloads the service definition) and only later runs launchctl bootstrap. If the CLI process dies between the two — closed terminal pane, Ctrl+C, SIGHUP — the service stays unloaded and KeepAlive cannot revive the gateway. No error is shown.

Steps to Reproduce

  1. hermes gateway start → confirm launchctl list | grep ai.hermes.gateway shows a PID.
  2. In a closable pane: hermes gateway restart --all
  3. Close the pane immediately.
  4. launchctl list | grep ai.hermes.gateway → empty. Gateway gone, no auto-recovery.

Expected

Service definition stays loaded; KeepAlive keeps the gateway alive.

Actual

launchctl bootout unloads the service. launchctl bootstrap never runs. Trace from log show --predicate 'process == "launchd"':

12:13:10.159  bootout initiated by: launchctl<-python3.11<-zsh<-zellij
12:13:10.159  signaled service: Terminated: 15
12:13:11.088  exited due to exit(1)
12:13:11.088  removing service: ai.hermes.gateway
12:13:11.088  service state: not running

No subsequent bootstrap event.

Component / Env

  • Gateway
  • macOS 15.4 (Darwin 25.4.0, arm64), Python 3.11.14, Hermes 0.14.0

Root Cause

hermes_cli/gateway.py:5234-5287 — the --all branch on macOS calls launchd_stop() (bootout) → kill_gateway_processeslaunchd_start() (bootstrap). bootout unloads, so the window between the two is unsafe.

The non---all path (launchd_restart, gateway.py:3021) already does the right thing — launchctl kickstart -k cycles the process under the same job, no unload.

Proposed Fix

In the --all macOS branch, use launchd_restart() (kickstart -k) instead of bootout/bootstrap. Exclude the current PID from the sweep so the restart isn't killed. PR follows.

Willing to Submit a PR

Yes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/cliCLI entry point, hermes_cli/, setup wizardcomp/gatewayGateway runner, session dispatch, deliverytype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions