tstest/natlab/vmtest: kill QEMU when test process dies (#19676)

Re-exec the test binary as a thin wrapper that holds a pipe inherited
from the test. When the test goes away (any reason, including SIGKILL,
panic, or OOM), the kernel closes the pipe write end; the wrapper sees
EOF and SIGKILLs itself, taking QEMU and its children with it.

Updates #13038

Change-Id: Ib2151098193551396c1d7bb51b07da3bd6b2cfb4

Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
This commit is contained in:
Fernando Serboncini
2026-05-07 16:14:27 -04:00
committed by GitHub
parent 76248a68b2
commit 495d3acc7b
3 changed files with 119 additions and 1 deletions
+9 -1
View File
@@ -211,7 +211,14 @@ func (e *Env) launchQEMU(name, logPath string, args []string) error {
}
cmd.Stdout = qemuLog
cmd.Stderr = qemuLog
parentPipe, err := killWithParent(cmd)
if err != nil {
devNull.Close()
qemuLog.Close()
return fmt.Errorf("killWithParent: %w", err)
}
if err := cmd.Start(); err != nil {
parentPipe.Close()
devNull.Close()
qemuLog.Close()
return fmt.Errorf("qemu for %s: %w", name, err)
@@ -224,8 +231,9 @@ func (e *Env) launchQEMU(name, logPath string, args []string) error {
go e.tailLogFile(e.ctx, name, logPath)
}
e.t.Cleanup(func() {
cmd.Process.Kill()
killProcessTree(cmd)
cmd.Wait()
parentPipe.Close()
devNull.Close()
qemuLog.Close()
// Dump tail of VM log on failure for debugging.