From 7934a118e93d8f3620e745a4e0fe4992efe1e8b4 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 8 Jul 2025 14:47:20 -0700 Subject: [PATCH] [exec] Write trailing newline to -pid-file and -internal-pid-file When executing command, otherwise it is not possible to know when the pid file is fully written. Resolves https://github.com/google/gvisor/issues/11851 This PR only changes `exec` command, and not other commands that write pid files. FUTURE_COPYBARA_INTEGRATE_REVIEW=https://github.com/google/gvisor/pull/11861 from stepancheg:pid-file 726d8d929ed6445063ddcb6a390cc23059de3f4e PiperOrigin-RevId: 780722929 --- runsc/cmd/exec.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/runsc/cmd/exec.go b/runsc/cmd/exec.go index 48ebacd35c..4075a2c94a 100644 --- a/runsc/cmd/exec.go +++ b/runsc/cmd/exec.go @@ -197,8 +197,8 @@ func (ex *Exec) exec(conf *config.Config, c *container.Container, e *control.Exe // Write the sandbox-internal pid if required. if ex.internalPidFile != "" { - pidStr := []byte(strconv.Itoa(int(pid))) - if err := os.WriteFile(ex.internalPidFile, pidStr, 0644); err != nil { + pidStr := fmt.Sprintf("%d\n", pid) + if err := os.WriteFile(ex.internalPidFile, []byte(pidStr), 0644); err != nil { return util.Errorf("writing internal pid file %q: %v", ex.internalPidFile, err) } } @@ -207,7 +207,8 @@ func (ex *Exec) exec(conf *config.Config, c *container.Container, e *control.Exe // users can safely assume that the internal pid file is ready after // `runsc exec -d` returns. if ex.pidFile != "" { - if err := os.WriteFile(ex.pidFile, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil { + pidStr := fmt.Sprintf("%d\n", os.Getpid()) + if err := os.WriteFile(ex.pidFile, []byte(pidStr), 0644); err != nil { return util.Errorf("writing pid file: %v", err) } } @@ -289,7 +290,11 @@ func (ex *Exec) execChildAndWait(waitStatus *unix.WaitStatus) subcommands.ExitSt pidb, err := os.ReadFile(pidFile) if err == nil { // File appeared, check whether pid is fully written. - pid, err := strconv.Atoi(string(pidb)) + pids, cut := strings.CutSuffix(string(pidb), "\n") + if !cut { + return false, nil + } + pid, err := strconv.Atoi(pids) if err != nil { return false, nil }