From 4bb03609bc95734644855976525d7203bb0da7f6 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Mon, 15 Sep 2025 11:40:34 -0600 Subject: [PATCH] tool/gocross: ensure child process error codes are propagated on non-Unix The Unix implementation of doExec propagates error codes by virtue of the fact that it does an execve; the replacement binary will return the exit code. On non-Unix, we need to simulate these semantics by checking for an ExitError and, when present, passing that value on to os.Exit. We also add error handling to the doExec call for the benefit of handling any errors where doExec fails before being able to execute the desired binary. Updates https://github.com/tailscale/corp/issues/29940 Signed-off-by: Aaron Klotz --- tool/gocross/exec_other.go | 12 +++++++++++- tool/gocross/gocross.go | 6 +++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tool/gocross/exec_other.go b/tool/gocross/exec_other.go index 7bce0c099..4dd74f84d 100644 --- a/tool/gocross/exec_other.go +++ b/tool/gocross/exec_other.go @@ -6,6 +6,7 @@ package main import ( + "errors" "os" "os/exec" ) @@ -16,5 +17,14 @@ func doExec(cmd string, args []string, env []string) error { c.Stdin = os.Stdin c.Stdout = os.Stdout c.Stderr = os.Stderr - return c.Run() + err := c.Run() + + // Propagate ExitErrors within this func to give us similar semantics to + // the Unix variant. + var ee *exec.ExitError + if errors.As(err, &ee) { + os.Exit(ee.ExitCode()) + } + + return err } diff --git a/tool/gocross/gocross.go b/tool/gocross/gocross.go index c71012d73..41fab3d58 100644 --- a/tool/gocross/gocross.go +++ b/tool/gocross/gocross.go @@ -114,7 +114,11 @@ func main() { } - doExec(filepath.Join(toolchain, "bin/go"), args, os.Environ()) + // Note that doExec only returns if the exec call failed. + if err := doExec(filepath.Join(toolchain, "bin", "go"), args, os.Environ()); err != nil { + fmt.Fprintf(os.Stderr, "executing process: %v\n", err) + os.Exit(1) + } } //go:embed gocross-wrapper.sh