mirror of
https://github.com/Cheviiot/Vintner.git
synced 2026-08-03 15:57:24 +00:00
Every wrapped tool invocation (cl/link/msbuild/etc via wine, plus the native cmd/findstr shims) now starts its child in its own process group and forwards SIGINT/SIGTERM to that group, escalating to SIGKILL after a 5s grace period if it doesn't exit. Previously, interactive Ctrl-C happened to work by accident (the child inherited the terminal's foreground process group and got the signal directly), but anything that signals vintner by PID alone - a CI job's timeout, a supervisor's `kill <pid>` - never reached the wine/wineserver tree underneath it, which got reparented to init and kept running: wasted CPU, held file locks, stray FIFOs/temp files. Verified two ways: a unit test (signals_test.go) that starts a detached `sleep 30`, signals the test process itself, and checks the child actually dies; and a real end-to-end run - killed an in-flight `msbuild` driver build by PID mid-compile and confirmed no orphaned msbuild/cl/link/vintner process was left behind (wineserver and its persistent service processes are expected to survive, by design - see pipeDrainGrace's doc comment).
46 lines
949 B
Go
46 lines
949 B
Go
package wrapper
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
// runNative handles the two tool names that need no Wine/MSVC install at
|
|
// all: `cmd` (strips a leading "//c" and execs the rest) and `findstr`
|
|
// (delegates to grep).
|
|
func runNative(tool string, args []string) int {
|
|
switch tool {
|
|
case "cmd":
|
|
if len(args) > 0 && args[0] == "//c" {
|
|
args = args[1:]
|
|
}
|
|
return execInherit(args)
|
|
case "findstr":
|
|
return execInherit(append([]string{"grep"}, args...))
|
|
}
|
|
return 127
|
|
}
|
|
|
|
func execInherit(args []string) int {
|
|
if len(args) == 0 {
|
|
return 0
|
|
}
|
|
cmd := exec.Command(args[0], args[1:]...)
|
|
cmd.Stdin = os.Stdin
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
setNewProcessGroup(cmd)
|
|
if err := cmd.Start(); err != nil {
|
|
return 127
|
|
}
|
|
stopSignals := forwardSignals(cmd.Process)
|
|
defer stopSignals()
|
|
if err := cmd.Wait(); err != nil {
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
return exitErr.ExitCode()
|
|
}
|
|
return 127
|
|
}
|
|
return 0
|
|
}
|