From 45f07215301eb43eb93616fe7c94cb111c68b30a Mon Sep 17 00:00:00 2001 From: Irbe Krumina Date: Sat, 27 Apr 2024 20:28:09 +0100 Subject: [PATCH] cmd/containerboot: wait on tailscaled process only (#11897) Modifies containerboot to wait on tailscaled process only, not on any child process of containerboot. Waiting on any subprocess was racing with Go's exec.Cmd.Run, used to run iptables commands and that starts its own subprocesses and waits on them. Containerboot itself does not run anything else except for tailscaled, so there shouldn't be a need to wait on anything else. Updates tailscale/tailscale#11593 Signed-off-by: Irbe Krumina --- cmd/containerboot/main.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cmd/containerboot/main.go b/cmd/containerboot/main.go index eb49d156f..f39811738 100644 --- a/cmd/containerboot/main.go +++ b/cmd/containerboot/main.go @@ -559,25 +559,26 @@ runLoop: log.Println("Startup complete, waiting for shutdown signal") startupTasksDone = true - // Reap all processes, since we are PID1 and need to collect zombies. We can - // only start doing this once we've stopped shelling out to things - // `tailscale up`, otherwise this goroutine can reap the CLI subprocesses - // and wedge bringup. + // Wait on tailscaled process. It won't + // be cleaned up by default when the + // container exits as it is not PID1. + // TODO (irbekrm): perhaps we can + // replace the reaper by a running + // cmd.Wait in a goroutine immediately + // after starting tailscaled? reaper := func() { defer wg.Done() for { var status unix.WaitStatus - pid, err := unix.Wait4(-1, &status, 0, nil) + _, err := unix.Wait4(daemonProcess.Pid, &status, 0, nil) if errors.Is(err, unix.EINTR) { continue } if err != nil { - log.Fatalf("Waiting for exited processes: %v", err) - } - if pid == daemonProcess.Pid { - log.Printf("Tailscaled exited") - os.Exit(0) + log.Fatalf("Waiting for tailscaled to exit: %v", err) } + log.Print("tailscaled exited") + os.Exit(0) } } wg.Add(1)