1package main
2
3import (
4	"fmt"
5	"io"
6	"log"
7	"os"
8	"os/signal"
9	"syscall"
10	"time"
11)
12
13func main() {
14	// Ensure that this process terminates when the test times out,
15	// even if the expected signal never arrives.
16	go func() {
17		io.Copy(io.Discard, os.Stdin)
18		log.Fatal("stdin is closed; terminating")
19	}()
20
21	// Register to receive all signals.
22	c := make(chan os.Signal, 1)
23	signal.Notify(c)
24
25	// Get console window handle.
26	kernel32 := syscall.NewLazyDLL("kernel32.dll")
27	getConsoleWindow := kernel32.NewProc("GetConsoleWindow")
28	hwnd, _, err := getConsoleWindow.Call()
29	if hwnd == 0 {
30		log.Fatal("no associated console: ", err)
31	}
32
33	// Send message to close the console window.
34	const _WM_CLOSE = 0x0010
35	user32 := syscall.NewLazyDLL("user32.dll")
36	postMessage := user32.NewProc("PostMessageW")
37	ok, _, err := postMessage.Call(hwnd, _WM_CLOSE, 0, 0)
38	if ok == 0 {
39		log.Fatal("post message failed: ", err)
40	}
41
42	sig := <-c
43
44	// Allow some time for the handler to complete if it's going to.
45	//
46	// (In https://go.dev/issue/41884 the handler returned immediately,
47	// which caused Windows to terminate the program before the goroutine
48	// that received the SIGTERM had a chance to actually clean up.)
49	time.Sleep(time.Second)
50
51	// Print the signal's name: "terminated" makes the test succeed.
52	fmt.Println(sig)
53}
54