Skip to content

Commit

Permalink
internal/version: ignore signals intended for the child process
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
zikaeroh authored and FiloSottile committed Mar 18, 2021
1 parent 3c153da commit 5564b1e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
14 changes: 14 additions & 0 deletions internal/version/signal_notunix.go
Original file line number Diff line number Diff line change
@@ -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}
15 changes: 15 additions & 0 deletions internal/version/signal_unix.go
Original file line number Diff line number Diff line change
@@ -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}
10 changes: 10 additions & 0 deletions internal/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"net/http"
"os"
"os/exec"
"os/signal"
"os/user"
"path"
"path/filepath"
Expand Down Expand Up @@ -64,6 +65,9 @@ func runGo(root string) {
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)
Expand Down Expand Up @@ -500,3 +504,9 @@ func dedupEnv(caseInsensitive bool, env []string) []string {
}
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...)
}

0 comments on commit 5564b1e

Please sign in to comment.