cmd/buildlet: handle shutdown on Windows reverse buildlets
This change makes room for a race between the main function exiting, and
the delay built into our halting process when shutting down a reverse
dialer.
Ideally, there would be no race, but plumbing the shutdown signal
through is a separate significant effort.
For golang/go#42604
Change-Id: I0762cb71eac50bcda7f0cd571e04396e98bff699
Reviewed-on: https://go-review.googlesource.com/c/build/+/331669
Trust: Alexander Rakoczy <alex@golang.org>
Run-TryBot: Alexander Rakoczy <alex@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/cmd/buildlet/buildlet.go b/cmd/buildlet/buildlet.go
index 824a453..aa991f2 100644
--- a/cmd/buildlet/buildlet.go
+++ b/cmd/buildlet/buildlet.go
@@ -102,7 +102,6 @@
// Functionality set non-nil by some platforms:
var (
- osHalt func()
configureSerialLogOutput func()
setOSRlimit func() error
)
@@ -251,6 +250,11 @@
log.Fatalf("Error dialing coordinator: %v", err)
}
log.Printf("buildlet reverse mode exiting.")
+ if *haltEntireOS {
+ // The coordinator disconnects before doHalt has time to
+ // execute. handleHalt has a 1s delay.
+ time.Sleep(5 * time.Second)
+ }
os.Exit(0)
}
}
@@ -1194,29 +1198,23 @@
// requests from doing anything from this point on in the
// remaining second.
log.Printf("Halting in 1 second.")
- time.AfterFunc(1*time.Second, doHalt)
-}
-
-func doHalt() {
- if *rebootOnHalt {
- if err := exec.Command("reboot").Run(); err != nil {
- log.Printf("Error running reboot: %v", err)
+ time.AfterFunc(1*time.Second, func() {
+ if *rebootOnHalt {
+ doReboot()
}
- os.Exit(0)
- }
- if !*haltEntireOS {
+ if *haltEntireOS {
+ doHalt()
+ }
log.Printf("Ending buildlet process due to halt.")
os.Exit(0)
return
- }
+ })
+}
+
+func doHalt() {
log.Printf("Halting machine.")
- time.AfterFunc(5*time.Second, func() { os.Exit(0) })
- if osHalt != nil {
- // TODO: Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/aa376868%28v=vs.85%29.aspx
- osHalt()
- os.Exit(0)
- }
// Backup mechanism, if exec hangs for any reason:
+ time.AfterFunc(5*time.Second, func() { os.Exit(0) })
var err error
switch runtime.GOOS {
case "openbsd":
@@ -1238,9 +1236,9 @@
err = errors.New("not respecting -halt flag on macOS in unknown environment")
}
case "windows":
- err = errors.New("not respsecting -halt flag on windows in unknown environment")
+ err = errors.New("not respecting -halt flag on Windows in unknown environment")
if runtime.GOARCH == "arm64" {
- err = exec.Command("shutdown /s").Run()
+ err = exec.Command("shutdown", "/s").Run()
}
default:
err = errors.New("no system-specific halt command run; will just end buildlet process")
@@ -1250,6 +1248,20 @@
os.Exit(0)
}
+func doReboot() {
+ log.Printf("Rebooting machine.")
+ var err error
+ switch runtime.GOOS {
+ case "windows":
+ err = exec.Command("shutdown", "/r").Run()
+ default:
+ err = exec.Command("reboot").Run()
+ }
+ log.Printf("Reboot: %v", err)
+ log.Printf("Ending buildlet process post-halt")
+ os.Exit(0)
+}
+
func handleRemoveAll(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "requires POST method", http.StatusBadRequest)
diff --git a/cmd/buildlet/stage0/stage0.go b/cmd/buildlet/stage0/stage0.go
index 8bb26d9..00d6f33 100644
--- a/cmd/buildlet/stage0/stage0.go
+++ b/cmd/buildlet/stage0/stage0.go
@@ -200,6 +200,15 @@
case "solaris/amd64", "illumos/amd64":
hostType := buildEnv
cmd.Args = append(cmd.Args, reverseHostTypeArgs(hostType)...)
+ case "windows/arm64":
+ switch buildEnv {
+ case "host-windows-arm64-mini":
+ cmd.Args = append(cmd.Args,
+ "--halt=true",
+ "--reverse-type="+buildEnv,
+ "--coordinator=farmer.golang.org:443",
+ )
+ }
}
// Release the serial port (if we opened it) so the buildlet
// process can open & write to it. At least on Windows, only