github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/toolchain/exec.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build !js && !wasip1 6 7 package toolchain 8 9 import ( 10 "os" 11 "os/exec" 12 "runtime" 13 "syscall" 14 15 "github.com/go-asm/go/cmd/go/base" 16 "github.com/go-asm/go/godebug" 17 ) 18 19 // execGoToolchain execs the Go toolchain with the given name (gotoolchain), 20 // GOROOT directory, and go command executable. 21 // The GOROOT directory is empty if we are invoking a command named 22 // gotoolchain found in $PATH. 23 func execGoToolchain(gotoolchain, dir, exe string) { 24 os.Setenv(targetEnv, gotoolchain) 25 if dir == "" { 26 os.Unsetenv("GOROOT") 27 } else { 28 os.Setenv("GOROOT", dir) 29 } 30 31 // On Windows, there is no syscall.Exec, so the best we can do 32 // is run a subprocess and exit with the same status. 33 // Doing the same on Unix would be a problem because it wouldn't 34 // propagate signals and such, but there are no signals on Windows. 35 // We also use the exec case when GODEBUG=gotoolchainexec=0, 36 // to allow testing this code even when not on Windows. 37 if godebug.New("#gotoolchainexec").Value() == "0" || runtime.GOOS == "windows" { 38 cmd := exec.Command(exe, os.Args[1:]...) 39 cmd.Stdin = os.Stdin 40 cmd.Stdout = os.Stdout 41 cmd.Stderr = os.Stderr 42 err := cmd.Run() 43 if err != nil { 44 if e, ok := err.(*exec.ExitError); ok && e.ProcessState != nil { 45 if e.ProcessState.Exited() { 46 os.Exit(e.ProcessState.ExitCode()) 47 } 48 base.Fatalf("exec %s: %s", gotoolchain, e.ProcessState) 49 } 50 base.Fatalf("exec %s: %s", exe, err) 51 } 52 os.Exit(0) 53 } 54 err := syscall.Exec(exe, os.Args, os.Environ()) 55 base.Fatalf("exec %s: %v", gotoolchain, err) 56 }