fix(gateway): support stop command for externally-started gateway

When gateway is started externally and the web handler attaches to it
via PID file, the stop command incorrectly returned "not_running" because
it only checked gateway.cmd (which is nil for attached gateways).

Now handles both cases:
1. Gateway started by handler: uses gateway.cmd.Process
2. Gateway started externally: uses gateway.pidData.PID with os.FindProcess

Fixes #2373

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
merlinmiao 2026-04-07 14:43:25 +08:00
parent 1da76b26c6
commit 78f8b7a0c4

View file

@ -452,18 +452,31 @@ func (h *Handler) StopGateway() {
// Assumes gateway.mu is held by the caller.
// Returns the PID of the stopped process and any error encountered.
func stopGatewayLocked() (int, error) {
if gateway.cmd == nil || gateway.cmd.Process == nil {
return 0, nil
}
pid := gateway.cmd.Process.Pid
// Send SIGTERM for graceful shutdown (SIGKILL on Windows)
var pid int
var sigErr error
if runtime.GOOS == "windows" {
sigErr = gateway.cmd.Process.Kill()
if gateway.cmd != nil && gateway.cmd.Process != nil {
// Gateway was started by us - use the cmd process
pid = gateway.cmd.Process.Pid
if runtime.GOOS == "windows" {
sigErr = gateway.cmd.Process.Kill()
} else {
sigErr = gateway.cmd.Process.Signal(syscall.SIGTERM)
}
} else if gateway.pidData != nil && gateway.pidData.PID > 0 {
// Gateway was started externally and we attached to it - use os.FindProcess
pid = gateway.pidData.PID
proc, err := os.FindProcess(pid)
if err != nil {
return pid, fmt.Errorf("failed to find process: %w", err)
}
if runtime.GOOS == "windows" {
sigErr = proc.Kill()
} else {
sigErr = proc.Signal(syscall.SIGTERM)
}
} else {
sigErr = gateway.cmd.Process.Signal(syscall.SIGTERM)
return 0, nil
}
if sigErr != nil {
@ -752,7 +765,8 @@ func (h *Handler) handleGatewayStop(w http.ResponseWriter, r *http.Request) {
gateway.mu.Lock()
defer gateway.mu.Unlock()
if gateway.cmd == nil || gateway.cmd.Process == nil {
// Check if gateway is running (either started by us or attached externally)
if gateway.cmd == nil && gateway.pidData == nil {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]any{
"status": "not_running",