Skip to content

fix(go-core): stop the server when the TUI exits or its parent dies - #1131

Merged
ElioNeto merged 1 commit into
developfrom
fix/go-core-orphan
Sep 9, 2026
Merged

fix(go-core): stop the server when the TUI exits or its parent dies#1131
ElioNeto merged 1 commit into
developfrom
fix/go-core-orphan

Conversation

@ElioNeto

@ElioNeto ElioNeto commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Problem

On Windows, go-core-server.exe stays alive after the TUI closes and has to be killed from Task Manager. stopGoCore() exists in packages/core/src/router/go-core.ts but nothing calls it, and Windows never signals a child when its parent exits. Each new TUI then finds the orphan on port 43001 (findAvailablePort) and starts yet another server on the next port, so orphans accumulate.

Fix

Two independent layers, so the server also goes away when the TUI crashes or is force-killed:

  • Spawner (TS): installExitHook(process, stopGoCore) registers a single once("exit") hook per host process; childEnv passes GO_CORE_PARENT_PID to the child alongside GO_CORE_PORT.
  • Server (Go): new package internal/parentwatch. Alive(pid) uses OpenProcess + GetExitCodeProcess on Windows and kill(pid, 0) elsewhere. Watch polls every 2s and cancels the server context when the parent is gone, which runs the existing graceful Shutdown. The watchdog only starts when GO_CORE_PARENT_PID is set, so standalone runs (Docker/VPS) are unaffected.

cmd/server/main.go also loses its errcheck and unused findings (server.Shutdown, os.Remove, two fmt.Fprintf, errorPool). Remaining golangci-lint findings in fs_handlers.go, health.go, metrics_handlers.go, session_crud_handlers.go and session_handlers_test.go are pre-existing and untouched.

Verification

  • go test ./cmd/server/ ./internal/parentwatch/: pass (4 new tests: own pid alive, exited child not alive, watch fires for exited parent, watch stops on cancel). GOOS=linux go vet also clean.
  • bun test packages/core/test/router/go-core.test.ts: 3 pass.
  • Real proof on Windows: built go-core-server.exe, started it with GO_CORE_PARENT_PID pointing to a PowerShell process that exits after 4s. /health returned 200 while the parent lived; log shows parent process 6620 exited, shutting down and the process was gone 2s after the parent.

🤖 Generated with Claude Code

go-core-server kept running on Windows after the TUI closed and had to be
killed from Task Manager. stopGoCore existed but nothing called it, and
Windows never signals a child when its parent exits. Each new TUI then
found the orphan on 43001 and started another server on the next port.

Two layers:

- The spawner registers a once("exit") hook on the host process that
  calls stopGoCore, and passes GO_CORE_PARENT_PID to the child.
- The Go server watches that PID every 2s (OpenProcess/GetExitCodeProcess
  on Windows, kill(pid, 0) elsewhere) and runs the existing graceful
  shutdown when the parent is gone, covering crashes and forced kills.

Also clears the errcheck and unused findings in cmd/server/main.go.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Sep 9, 2026

Copy link
Copy Markdown

@ElioNeto
ElioNeto marked this pull request as ready for review September 9, 2026 14:04
@ElioNeto
ElioNeto merged commit 96bd1de into develop Sep 9, 2026
4 checks passed
@ElioNeto
ElioNeto deleted the fix/go-core-orphan branch September 9, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants