cmd/racebuild: destroy in-flight gomotes on interrupt

Updates golang/go#24354.

Change-Id: I8db0dd81a669b1e75fc82295292d2d57d1c1935b
Reviewed-on: https://go-review.googlesource.com/112878
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/cmd/racebuild/racebuild.go b/cmd/racebuild/racebuild.go
index 2dda8ab..9578e8e 100644
--- a/cmd/racebuild/racebuild.go
+++ b/cmd/racebuild/racebuild.go
@@ -19,6 +19,7 @@
 	"log"
 	"os"
 	"os/exec"
+	"os/signal"
 	"path/filepath"
 	"regexp"
 	"strings"
@@ -173,7 +174,16 @@
 	}
 
 	// Start build on all platforms in parallel.
-	g, ctx := errgroup.WithContext(context.Background())
+	// On interrupt, destroy any in-flight builders before exiting.
+	ctx, cancel := context.WithCancel(context.Background())
+	shutdown := make(chan os.Signal, 1)
+	signal.Notify(shutdown, os.Interrupt)
+	go func() {
+		<-shutdown
+		cancel()
+	}()
+
+	g, ctx := errgroup.WithContext(ctx)
 	for _, p := range platforms {
 		if !platformEnabled[p.Name()] {
 			continue
@@ -209,7 +219,7 @@
 func (p *Platform) Build(ctx context.Context) error {
 	// Create gomote instance (or reuse an existing instance for debugging).
 	var lastErr error
-	for i := 0; p.Inst == "" && i < 10; i++ {
+	for p.Inst == "" {
 		inst, err := p.Gomote(ctx, "create", p.Type)
 		if err != nil {
 			select {
@@ -229,9 +239,6 @@
 		p.Inst = strings.Trim(string(inst), " \t\n")
 		defer p.Gomote(context.Background(), "destroy", p.Inst)
 	}
-	if p.Inst == "" {
-		return lastErr
-	}
 	log.Printf("%s: using instance %v", p.Name(), p.Inst)
 
 	// put14