Source file src/cmd/go/internal/toolchain/exec.go

     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  	"cmd/go/internal/base"
    11  	"internal/godebug"
    12  	"os"
    13  	"os/exec"
    14  	"runtime"
    15  	"syscall"
    16  )
    17  
    18  // execGoToolchain execs the Go toolchain with the given name (gotoolchain),
    19  // GOROOT directory, and go command executable.
    20  // The GOROOT directory is empty if we are invoking a command named
    21  // gotoolchain found in $PATH.
    22  func execGoToolchain(gotoolchain, dir, exe string) {
    23  	os.Setenv(targetEnv, gotoolchain)
    24  	if dir == "" {
    25  		os.Unsetenv("GOROOT")
    26  	} else {
    27  		os.Setenv("GOROOT", dir)
    28  	}
    29  
    30  	// On Windows, there is no syscall.Exec, so the best we can do
    31  	// is run a subprocess and exit with the same status.
    32  	// Doing the same on Unix would be a problem because it wouldn't
    33  	// propagate signals and such, but there are no signals on Windows.
    34  	// We also use the exec case when GODEBUG=gotoolchainexec=0,
    35  	// to allow testing this code even when not on Windows.
    36  	if godebug.New("#gotoolchainexec").Value() == "0" || runtime.GOOS == "windows" {
    37  		cmd := exec.Command(exe, os.Args[1:]...)
    38  		cmd.Stdin = os.Stdin
    39  		cmd.Stdout = os.Stdout
    40  		cmd.Stderr = os.Stderr
    41  		err := cmd.Run()
    42  		if err != nil {
    43  			if e, ok := err.(*exec.ExitError); ok && e.ProcessState != nil {
    44  				if e.ProcessState.Exited() {
    45  					os.Exit(e.ProcessState.ExitCode())
    46  				}
    47  				base.Fatalf("exec %s: %s", gotoolchain, e.ProcessState)
    48  			}
    49  			base.Fatalf("exec %s: %s", exe, err)
    50  		}
    51  		os.Exit(0)
    52  	}
    53  	err := syscall.Exec(exe, os.Args, os.Environ())
    54  	base.Fatalf("exec %s: %v", gotoolchain, err)
    55  }
    56  

View as plain text