Source file
src/os/signal/signal_windows_test.go
1
2
3
4
5 package signal
6
7 import (
8 "bufio"
9 "fmt"
10 "internal/testenv"
11 "os"
12 "path/filepath"
13 "strings"
14 "syscall"
15 "testing"
16 )
17
18 func sendCtrlBreak(pid int) error {
19 d, e := syscall.LoadDLL("kernel32.dll")
20 if e != nil {
21 return fmt.Errorf("LoadDLL: %v\n", e)
22 }
23 p, e := d.FindProc("GenerateConsoleCtrlEvent")
24 if e != nil {
25 return fmt.Errorf("FindProc: %v\n", e)
26 }
27 r, _, e := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid))
28 if r == 0 {
29 return fmt.Errorf("GenerateConsoleCtrlEvent: %v\n", e)
30 }
31 return nil
32 }
33
34 func TestCtrlBreak(t *testing.T) {
35
36 const source = `
37 package main
38
39 import (
40 "fmt"
41 "log"
42 "os"
43 "os/signal"
44 "time"
45 )
46
47
48 func main() {
49 c := make(chan os.Signal, 10)
50 signal.Notify(c)
51 fmt.Println("ready")
52 select {
53 case s := <-c:
54 if s != os.Interrupt {
55 log.Fatalf("Wrong signal received: got %q, want %q\n", s, os.Interrupt)
56 }
57 case <-time.After(3 * time.Second):
58 log.Fatalf("Timeout waiting for Ctrl+Break\n")
59 }
60 }
61 `
62 tmp := t.TempDir()
63
64
65 name := filepath.Join(tmp, "ctrlbreak")
66 src := name + ".go"
67 f, err := os.Create(src)
68 if err != nil {
69 t.Fatalf("Failed to create %v: %v", src, err)
70 }
71 defer f.Close()
72 f.Write([]byte(source))
73
74
75 exe := name + ".exe"
76 defer os.Remove(exe)
77 o, err := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", exe, src).CombinedOutput()
78 if err != nil {
79 t.Fatalf("Failed to compile: %v\n%v", err, string(o))
80 }
81
82
83 cmd := testenv.Command(t, exe)
84 var buf strings.Builder
85 cmd.Stderr = &buf
86 stdout, err := cmd.StdoutPipe()
87 if err != nil {
88 t.Fatalf("StdoutPipe failed: %v", err)
89 }
90 cmd.SysProcAttr = &syscall.SysProcAttr{
91 CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
92 }
93 err = cmd.Start()
94 if err != nil {
95 t.Fatalf("Start failed: %v", err)
96 }
97
98 outReader := bufio.NewReader(stdout)
99 errCh := make(chan error, 1)
100 go func() {
101 if line, err := outReader.ReadString('\n'); err != nil {
102 errCh <- fmt.Errorf("could not read stdout: %v", err)
103 } else if strings.TrimSpace(line) != "ready" {
104 errCh <- fmt.Errorf("unexpected message: %v", line)
105 } else {
106 errCh <- sendCtrlBreak(cmd.Process.Pid)
107 }
108 }()
109
110 if err := <-errCh; err != nil {
111 t.Fatal(err)
112 }
113 err = cmd.Wait()
114 if err != nil {
115 t.Fatalf("Program exited with error: %v\n%v", err, buf.String())
116 }
117 }
118
View as plain text