Home | History | Annotate | Download | only in signal
      1 // Copyright 2012 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package signal
      6 
      7 import (
      8 	"bytes"
      9 	"internal/testenv"
     10 	"io/ioutil"
     11 	"os"
     12 	"os/exec"
     13 	"path/filepath"
     14 	"syscall"
     15 	"testing"
     16 	"time"
     17 )
     18 
     19 func sendCtrlBreak(t *testing.T, pid int) {
     20 	d, e := syscall.LoadDLL("kernel32.dll")
     21 	if e != nil {
     22 		t.Fatalf("LoadDLL: %v\n", e)
     23 	}
     24 	p, e := d.FindProc("GenerateConsoleCtrlEvent")
     25 	if e != nil {
     26 		t.Fatalf("FindProc: %v\n", e)
     27 	}
     28 	r, _, e := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid))
     29 	if r == 0 {
     30 		t.Fatalf("GenerateConsoleCtrlEvent: %v\n", e)
     31 	}
     32 }
     33 
     34 func TestCtrlBreak(t *testing.T) {
     35 	// create source file
     36 	const source = `
     37 package main
     38 
     39 import (
     40 	"log"
     41 	"os"
     42 	"os/signal"
     43 	"time"
     44 )
     45 
     46 
     47 func main() {
     48 	c := make(chan os.Signal, 10)
     49 	signal.Notify(c)
     50 	select {
     51 	case s := <-c:
     52 		if s != os.Interrupt {
     53 			log.Fatalf("Wrong signal received: got %q, want %q\n", s, os.Interrupt)
     54 		}
     55 	case <-time.After(3 * time.Second):
     56 		log.Fatalf("Timeout waiting for Ctrl+Break\n")
     57 	}
     58 }
     59 `
     60 	tmp, err := ioutil.TempDir("", "TestCtrlBreak")
     61 	if err != nil {
     62 		t.Fatal("TempDir failed: ", err)
     63 	}
     64 	defer os.RemoveAll(tmp)
     65 
     66 	// write ctrlbreak.go
     67 	name := filepath.Join(tmp, "ctlbreak")
     68 	src := name + ".go"
     69 	f, err := os.Create(src)
     70 	if err != nil {
     71 		t.Fatalf("Failed to create %v: %v", src, err)
     72 	}
     73 	defer f.Close()
     74 	f.Write([]byte(source))
     75 
     76 	// compile it
     77 	exe := name + ".exe"
     78 	defer os.Remove(exe)
     79 	o, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src).CombinedOutput()
     80 	if err != nil {
     81 		t.Fatalf("Failed to compile: %v\n%v", err, string(o))
     82 	}
     83 
     84 	// run it
     85 	cmd := exec.Command(exe)
     86 	var b bytes.Buffer
     87 	cmd.Stdout = &b
     88 	cmd.Stderr = &b
     89 	cmd.SysProcAttr = &syscall.SysProcAttr{
     90 		CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
     91 	}
     92 	err = cmd.Start()
     93 	if err != nil {
     94 		t.Fatalf("Start failed: %v", err)
     95 	}
     96 	go func() {
     97 		time.Sleep(1 * time.Second)
     98 		sendCtrlBreak(t, cmd.Process.Pid)
     99 	}()
    100 	err = cmd.Wait()
    101 	if err != nil {
    102 		t.Fatalf("Program exited with error: %v\n%v", err, string(b.Bytes()))
    103 	}
    104 }
    105