@@ -180,7 +180,7 @@ func RunBazeliskWithArgsFuncAndConfigAndOut(argsFunc ArgsFunc, repos *Repositori
180180 return 0 , nil
181181 }
182182
183- exitCode , err := runBazel (bazelInstallation .Path , args , out , config )
183+ exitCode , err := runBazel (bazelInstallation .Path , args , out , config , isRunCommand ( args ) )
184184 if err != nil {
185185 return - 1 , fmt .Errorf ("could not run Bazel: %v" , err )
186186 }
@@ -727,11 +727,35 @@ func makeBazelCmd(bazel string, args []string, out io.Writer, config config.Conf
727727 return cmd , nil
728728}
729729
730- func runBazel (bazel string , args []string , out io.Writer , config config.Config ) (int , error ) {
730+ func isRunCommand (args []string ) bool {
731+ for _ , arg := range args {
732+ if arg == "--" {
733+ return false
734+ }
735+ if arg == "run" {
736+ return true
737+ }
738+ }
739+ return false
740+ }
741+
742+ func runBazel (bazel string , args []string , out io.Writer , config config.Config , useExecOnUnix bool ) (int , error ) {
731743 cmd , makeCmdErr := makeBazelCmd (bazel , args , out , config )
732744 if makeCmdErr != nil {
733745 return 1 , makeCmdErr
734746 }
747+ if useExecOnUnix && runtime .GOOS != "windows" {
748+ execPath := cmd .Path
749+ execArgs := cmd .Args
750+ execEnv := cmd .Env
751+ err := syscall .Exec (execPath , execArgs , execEnv )
752+ if err != nil {
753+ return 1 , fmt .Errorf ("could not exec Bazel: %v" , err )
754+ }
755+ // This code is unreachable if exec succeeds
756+ return 0 , nil
757+ }
758+
735759 err := cmd .Start ()
736760 if err != nil {
737761 return 1 , fmt .Errorf ("could not start Bazel: %v" , err )
@@ -750,7 +774,6 @@ func runBazel(bazel string, args []string, out io.Writer, config config.Config)
750774 // by the terminal. As a side effect, we also suppress the printing of a
751775 // Go stack trace upon receiving SIGQUIT, which is unhelpful as users tend
752776 // to report it instead of the far more valuable Java thread dump.
753- // TODO(#512): We may want to treat a `bazel run` command differently.
754777 // Since signal handlers are process-wide global state and bazelisk may be
755778 // used as a library, reset the signal handlers after the process exits.
756779 sigCh := make (chan os.Signal , 1 )
@@ -761,7 +784,18 @@ func runBazel(bazel string, args []string, out io.Writer, config config.Config)
761784 if err != nil {
762785 if exitError , ok := err .(* exec.ExitError ); ok {
763786 waitStatus := exitError .Sys ().(syscall.WaitStatus )
764- return waitStatus .ExitStatus (), nil
787+ // it's only correct to use waitStatus.ExitStatus when the process terminated normally, i.e. waitStatus.Exited() == true
788+ if waitStatus .Exited () {
789+ return waitStatus .ExitStatus (), nil
790+ }
791+ // if the process was terminated by a signal on a POSIX-compatible system, let's report its exit code in the same way
792+ // as shells do - as 128 + signal number.
793+ // It's not a perfect solution, because information that a signal has terminated the process is lost,
794+ // but at least we propagate a proper exit code.
795+ if runtime .GOOS != "windows" && waitStatus .Signaled () {
796+ return 128 + int (waitStatus .Signal ()), nil
797+ }
798+ return 1 , fmt .Errorf ("unexpected wait status of Bazel: %v" , waitStatus )
765799 }
766800 return 1 , fmt .Errorf ("could not launch Bazel: %v" , err )
767801 }
@@ -776,7 +810,7 @@ func getIncompatibleFlags(bazelPath, cmd string, config config.Config) ([]string
776810 }
777811
778812 out := strings.Builder {}
779- if _ , err := runBazel (bazelPath , []string {"help" , cmd , "--short" }, & out , config ); err != nil {
813+ if _ , err := runBazel (bazelPath , []string {"help" , cmd , "--short" }, & out , config , false ); err != nil {
780814 return nil , fmt .Errorf ("unable to determine incompatible flags with binary %s: %v" , bazelPath , err )
781815 }
782816
@@ -852,7 +886,7 @@ func shutdownIfNeeded(bazelPath string, startupOptions []string, config config.C
852886
853887 args := append (startupOptions , "shutdown" )
854888 fmt .Printf ("bazel %s\n " , strings .Join (args , " " ))
855- exitCode , err := runBazel (bazelPath , args , nil , config )
889+ exitCode , err := runBazel (bazelPath , args , nil , config , false )
856890 fmt .Printf ("\n " )
857891 if err != nil {
858892 log .Fatalf ("failed to run bazel shutdown: %v" , err )
@@ -871,7 +905,7 @@ func cleanIfNeeded(bazelPath string, startupOptions []string, config config.Conf
871905
872906 args := append (startupOptions , "clean" , "--expunge" )
873907 fmt .Printf ("bazel %s\n " , strings .Join (args , " " ))
874- exitCode , err := runBazel (bazelPath , args , nil , config )
908+ exitCode , err := runBazel (bazelPath , args , nil , config , false )
875909 fmt .Printf ("\n " )
876910 if err != nil {
877911 log .Fatalf ("failed to run clean: %v" , err )
@@ -1070,7 +1104,7 @@ func testWithBazelAtCommit(bazelCommit string, args []string, bazeliskHome strin
10701104 shutdownIfNeeded (bazelPath , startupOptions , config )
10711105 cleanIfNeeded (bazelPath , startupOptions , config )
10721106 fmt .Printf ("bazel %s\n " , strings .Join (args , " " ))
1073- bazelExitCode , err := runBazel (bazelPath , args , nil , config )
1107+ bazelExitCode , err := runBazel (bazelPath , args , nil , config , false )
10741108 if err != nil {
10751109 return - 1 , fmt .Errorf ("could not run Bazel: %v" , err )
10761110 }
@@ -1087,7 +1121,7 @@ func migrate(bazelPath string, baseArgs []string, flags []string, config config.
10871121 shutdownIfNeeded (bazelPath , startupOptions , config )
10881122 cleanIfNeeded (bazelPath , startupOptions , config )
10891123 fmt .Printf ("bazel %s\n " , strings .Join (args , " " ))
1090- exitCode , err := runBazel (bazelPath , args , nil , config )
1124+ exitCode , err := runBazel (bazelPath , args , nil , config , false )
10911125 if err != nil {
10921126 log .Fatalf ("could not run Bazel: %v" , err )
10931127 }
@@ -1102,7 +1136,7 @@ func migrate(bazelPath string, baseArgs []string, flags []string, config config.
11021136 shutdownIfNeeded (bazelPath , startupOptions , config )
11031137 cleanIfNeeded (bazelPath , startupOptions , config )
11041138 fmt .Printf ("bazel %s\n " , strings .Join (args , " " ))
1105- exitCode , err = runBazel (bazelPath , args , nil , config )
1139+ exitCode , err = runBazel (bazelPath , args , nil , config , false )
11061140 if err != nil {
11071141 log .Fatalf ("could not run Bazel: %v" , err )
11081142 }
@@ -1120,7 +1154,7 @@ func migrate(bazelPath string, baseArgs []string, flags []string, config config.
11201154 shutdownIfNeeded (bazelPath , startupOptions , config )
11211155 cleanIfNeeded (bazelPath , startupOptions , config )
11221156 fmt .Printf ("bazel %s\n " , strings .Join (args , " " ))
1123- exitCode , err = runBazel (bazelPath , args , nil , config )
1157+ exitCode , err = runBazel (bazelPath , args , nil , config , false )
11241158 if err != nil {
11251159 log .Fatalf ("could not run Bazel: %v" , err )
11261160 }
0 commit comments