Source file src/os/signal/signal_plan9_test.go

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

View as plain text