github.com/zxy12/golang_with_comment@v0.0.0-20190701084843-0e6b2aff5ef3/os/signal/signal_plan9_test.go (about)

     1  // Copyright 2009 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  	"os"
     9  	"runtime"
    10  	"syscall"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) {
    16  	select {
    17  	case s := <-c:
    18  		if s != sig {
    19  			t.Fatalf("signal was %v, want %v", s, sig)
    20  		}
    21  	case <-time.After(1 * time.Second):
    22  		t.Fatalf("timeout waiting for %v", sig)
    23  	}
    24  }
    25  
    26  // Test that basic signal handling works.
    27  func TestSignal(t *testing.T) {
    28  	// Ask for hangup
    29  	c := make(chan os.Signal, 1)
    30  	Notify(c, syscall.Note("hangup"))
    31  	defer Stop(c)
    32  
    33  	// Send this process a hangup
    34  	t.Logf("hangup...")
    35  	postNote(syscall.Getpid(), "hangup")
    36  	waitSig(t, c, syscall.Note("hangup"))
    37  
    38  	// Ask for everything we can get.
    39  	c1 := make(chan os.Signal, 1)
    40  	Notify(c1)
    41  
    42  	// Send this process an alarm
    43  	t.Logf("alarm...")
    44  	postNote(syscall.Getpid(), "alarm")
    45  	waitSig(t, c1, syscall.Note("alarm"))
    46  
    47  	// Send two more hangups, to make sure that
    48  	// they get delivered on c1 and that not reading
    49  	// from c does not block everything.
    50  	t.Logf("hangup...")
    51  	postNote(syscall.Getpid(), "hangup")
    52  	waitSig(t, c1, syscall.Note("hangup"))
    53  	t.Logf("hangup...")
    54  	postNote(syscall.Getpid(), "hangup")
    55  	waitSig(t, c1, syscall.Note("hangup"))
    56  
    57  	// The first SIGHUP should be waiting for us on c.
    58  	waitSig(t, c, syscall.Note("hangup"))
    59  }
    60  
    61  func TestStress(t *testing.T) {
    62  	dur := 3 * time.Second
    63  	if testing.Short() {
    64  		dur = 100 * time.Millisecond
    65  	}
    66  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
    67  	done := make(chan bool)
    68  	finished := make(chan bool)
    69  	go func() {
    70  		sig := make(chan os.Signal, 1)
    71  		Notify(sig, syscall.Note("alarm"))
    72  		defer Stop(sig)
    73  	Loop:
    74  		for {
    75  			select {
    76  			case <-sig:
    77  			case <-done:
    78  				break Loop
    79  			}
    80  		}
    81  		finished <- true
    82  	}()
    83  	go func() {
    84  	Loop:
    85  		for {
    86  			select {
    87  			case <-done:
    88  				break Loop
    89  			default:
    90  				postNote(syscall.Getpid(), "alarm")
    91  				runtime.Gosched()
    92  			}
    93  		}
    94  		finished <- true
    95  	}()
    96  	time.Sleep(dur)
    97  	close(done)
    98  	<-finished
    99  	<-finished
   100  	// When run with 'go test -cpu=1,2,4' alarm from this test can slip
   101  	// into subsequent TestSignal() causing failure.
   102  	// Sleep for a while to reduce the possibility of the failure.
   103  	time.Sleep(10 * time.Millisecond)
   104  }
   105  
   106  // Test that Stop cancels the channel's registrations.
   107  func TestStop(t *testing.T) {
   108  	if testing.Short() {
   109  		t.Skip("skipping in short mode")
   110  	}
   111  	sigs := []string{
   112  		"alarm",
   113  		"hangup",
   114  	}
   115  
   116  	for _, sig := range sigs {
   117  		// Send the signal.
   118  		// If it's alarm, we should not see it.
   119  		// If it's hangup, maybe we'll die. Let the flag tell us what to do.
   120  		if sig != "hangup" {
   121  			postNote(syscall.Getpid(), sig)
   122  		}
   123  		time.Sleep(100 * time.Millisecond)
   124  
   125  		// Ask for signal
   126  		c := make(chan os.Signal, 1)
   127  		Notify(c, syscall.Note(sig))
   128  		defer Stop(c)
   129  
   130  		// Send this process that signal
   131  		postNote(syscall.Getpid(), sig)
   132  		waitSig(t, c, syscall.Note(sig))
   133  
   134  		Stop(c)
   135  		select {
   136  		case s := <-c:
   137  			t.Fatalf("unexpected signal %v", s)
   138  		case <-time.After(100 * time.Millisecond):
   139  			// nothing to read - good
   140  		}
   141  
   142  		// Send the signal.
   143  		// If it's alarm, we should not see it.
   144  		// If it's hangup, maybe we'll die. Let the flag tell us what to do.
   145  		if sig != "hangup" {
   146  			postNote(syscall.Getpid(), sig)
   147  		}
   148  
   149  		select {
   150  		case s := <-c:
   151  			t.Fatalf("unexpected signal %v", s)
   152  		case <-time.After(100 * time.Millisecond):
   153  			// nothing to read - good
   154  		}
   155  	}
   156  }
   157  
   158  func itoa(val int) string {
   159  	if val < 0 {
   160  		return "-" + itoa(-val)
   161  	}
   162  	var buf [32]byte // big enough for int64
   163  	i := len(buf) - 1
   164  	for val >= 10 {
   165  		buf[i] = byte(val%10 + '0')
   166  		i--
   167  		val /= 10
   168  	}
   169  	buf[i] = byte(val + '0')
   170  	return string(buf[i:])
   171  }
   172  
   173  func postNote(pid int, note string) error {
   174  	f, err := os.OpenFile("/proc/"+itoa(pid)+"/note", os.O_WRONLY, 0)
   175  	if err != nil {
   176  		return err
   177  	}
   178  	defer f.Close()
   179  	_, err = f.Write([]byte(note))
   180  	return err
   181  }