internal/version: ignore signals intended for the child process
Since the underlying toolchain is run as a child process (and not
exec'd), signals that are sent to this process (for example, an
interrupt sent by a shell) will be handled by both the parent and the
child. This poses a problem for signals like SIGQUIT, where both
processes' runtimes attempt to write out information to the same output.
Before running the final command, start a signal handler that will
ignore a signal sent to the parent, emulating the behavior of go run.
This code is a modified version of cmd/go/internal/base.
Fixes golang/go#36976.
Change-Id: I29aa699dc059fd448aa9478f729ed8d90379616b
Reviewed-on: https://go-review.googlesource.com/c/dl/+/217765
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
diff --git a/internal/version/signal_notunix.go b/internal/version/signal_notunix.go
new file mode 100644
index 0000000..506655d
--- /dev/null
+++ b/internal/version/signal_notunix.go
@@ -0,0 +1,14 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build plan9 || windows
+// +build plan9 windows
+
+package version
+
+import (
+ "os"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt}
diff --git a/internal/version/signal_unix.go b/internal/version/signal_unix.go
new file mode 100644
index 0000000..e9b9fb9
--- /dev/null
+++ b/internal/version/signal_unix.go
@@ -0,0 +1,15 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || js || linux || netbsd || openbsd || solaris
+// +build aix darwin dragonfly freebsd js linux netbsd openbsd solaris
+
+package version
+
+import (
+ "os"
+ "syscall"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT}
diff --git a/internal/version/version.go b/internal/version/version.go
index 866e4ad..98e5d4a 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -18,6 +18,7 @@
"net/http"
"os"
"os/exec"
+ "os/signal"
"os/user"
"path"
"path/filepath"
@@ -64,6 +65,9 @@
newPath += string(filepath.ListSeparator) + p
}
cmd.Env = dedupEnv(caseInsensitiveEnv, append(os.Environ(), "GOROOT="+root, "PATH="+newPath))
+
+ handleSignals()
+
if err := cmd.Run(); err != nil {
// TODO: return the same exit status maybe.
os.Exit(1)
@@ -500,3 +504,9 @@
}
return out
}
+
+func handleSignals() {
+ // Ensure that signals intended for the child process are not handled by
+ // this process' runtime (e.g. SIGQUIT). See issue #36976.
+ signal.Notify(make(chan os.Signal), signalsToIgnore...)
+}