package main import ( "fmt" "io" "log" "os" "os/signal" "syscall" "time" ) func main() { // Ensure that this process terminates when the test times out, // even if the expected signal never arrives. go func() { io.Copy(io.Discard, os.Stdin) log.Fatal("stdin is closed; terminating") }() // Register to receive all signals. c := make(chan os.Signal, 1) signal.Notify(c) // Get console window handle. kernel32 := syscall.NewLazyDLL("kernel32.dll") getConsoleWindow := kernel32.NewProc("GetConsoleWindow") hwnd, _, err := getConsoleWindow.Call() if hwnd == 0 { log.Fatal("no associated console: ", err) } // Send message to close the console window. const _WM_CLOSE = 0x0010 user32 := syscall.NewLazyDLL("user32.dll") postMessage := user32.NewProc("PostMessageW") ok, _, err := postMessage.Call(hwnd, _WM_CLOSE, 0, 0) if ok == 0 { log.Fatal("post message failed: ", err) } sig := <-c // Allow some time for the handler to complete if it's going to. // // (In https://go.dev/issue/41884 the handler returned immediately, // which caused Windows to terminate the program before the goroutine // that received the SIGTERM had a chance to actually clean up.) time.Sleep(time.Second) // Print the signal's name: "terminated" makes the test succeed. fmt.Println(sig) }