| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- //go:build unix
- package runner
- import (
- "os"
- "os/exec"
- "os/signal"
- "syscall"
- )
- // startSignalForwarding installs handlers for SIGINT, SIGTERM, and SIGHUP and
- // forwards them to proc. The returned stop function removes the handlers and
- // drains the channel; callers should defer-call it.
- //
- // We deliberately do NOT exit on signal receipt — the child gets the signal
- // and owns its shutdown lifecycle; we just relay and keep waiting for it.
- func startSignalForwarding(proc *os.Process) func() {
- ch := make(chan os.Signal, 4)
- signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
- done := make(chan struct{})
- go func() {
- for {
- select {
- case sig := <-ch:
- _ = proc.Signal(sig)
- case <-done:
- return
- }
- }
- }()
- return func() {
- signal.Stop(ch)
- close(done)
- }
- }
- // extractSignal pulls the signal from an *exec.ExitError on Unix.
- // If the error wasn't a signal termination, ok is false.
- func extractSignal(exitErr *exec.ExitError) (syscall.Signal, bool) {
- ws, ok := exitErr.Sys().(syscall.WaitStatus)
- if !ok {
- return 0, false
- }
- if !ws.Signaled() {
- return 0, false
- }
- return ws.Signal(), true
- }
|