mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: block console ctrlhandler when the signal is handled
Fixes #41884
I can confirm this change fixes my issue.
I can't confirm that this doesn't break any and everything else.
I see that this code has been tweaked repeatedly, so I would really welcome guidance into further testing.
Change-Id: I1986dd0c2f30cfe10257f0d8c658988d6986f7a6
GitHub-Last-Rev: 92f02c9697
GitHub-Pull-Request: golang/go#41886
Reviewed-on: https://go-review.googlesource.com/c/go/+/261057
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
parent
ff9e8364c6
commit
8cfa01943a
3 changed files with 90 additions and 0 deletions
|
|
@ -11,6 +11,7 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
|
@ -79,6 +80,69 @@ func sendCtrlBreak(pid int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// TestCtrlHandler tests that Go can gracefully handle closing the console window.
|
||||
// See https://golang.org/issues/41884.
|
||||
func TestCtrlHandler(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
t.Parallel()
|
||||
|
||||
// build go program
|
||||
exe := filepath.Join(t.TempDir(), "test.exe")
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, "testdata/testwinsignal/main.go")
|
||||
out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to build go exe: %v\n%s", err, out)
|
||||
}
|
||||
|
||||
// run test program
|
||||
cmd = exec.Command(exe)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
outPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create stdout pipe: %v", err)
|
||||
}
|
||||
outReader := bufio.NewReader(outPipe)
|
||||
|
||||
// in a new command window
|
||||
const _CREATE_NEW_CONSOLE = 0x00000010
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
CreationFlags: _CREATE_NEW_CONSOLE,
|
||||
HideWindow: true,
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
t.Fatalf("Start failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
cmd.Process.Kill()
|
||||
cmd.Wait()
|
||||
}()
|
||||
|
||||
// wait for child to be ready to receive signals
|
||||
if line, err := outReader.ReadString('\n'); err != nil {
|
||||
t.Fatalf("could not read stdout: %v", err)
|
||||
} else if strings.TrimSpace(line) != "ready" {
|
||||
t.Fatalf("unexpected message: %s", line)
|
||||
}
|
||||
|
||||
// gracefully kill pid, this closes the command window
|
||||
if err := exec.Command("taskkill.exe", "/pid", strconv.Itoa(cmd.Process.Pid)).Run(); err != nil {
|
||||
t.Fatalf("failed to kill: %v", err)
|
||||
}
|
||||
|
||||
// check child received, handled SIGTERM
|
||||
if line, err := outReader.ReadString('\n'); err != nil {
|
||||
t.Fatalf("could not read stdout: %v", err)
|
||||
} else if expected, got := syscall.SIGTERM.String(), strings.TrimSpace(line); expected != got {
|
||||
t.Fatalf("Expected '%s' got: %s", expected, got)
|
||||
}
|
||||
|
||||
// check child exited gracefully, did not timeout
|
||||
if err := cmd.Wait(); err != nil {
|
||||
t.Fatalf("Program exited with error: %v\n%s", err, &stderr)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLibraryCtrlHandler tests that Go DLL allows calling program to handle console control events.
|
||||
// See https://golang.org/issues/35965.
|
||||
func TestLibraryCtrlHandler(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue