Source file src/pkg/os/signal/signal.go
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 implements access to incoming signals.
6 package signal
7
8 // BUG(rsc): This package is not yet implemented on Plan 9 and Windows.
9
10 import (
11 "os"
12 "sync"
13 )
14
15 var handlers struct {
16 sync.Mutex
17 list []handler
18 }
19
20 type handler struct {
21 c chan<- os.Signal
22 sig os.Signal
23 all bool
24 }
25
26 // Notify causes package signal to relay incoming signals to c.
27 // If no signals are listed, all incoming signals will be relayed to c.
28 // Otherwise, just the listed signals will.
29 //
30 // Package signal will not block sending to c: the caller must ensure
31 // that c has sufficient buffer space to keep up with the expected
32 // signal rate. For a channel used for notification of just one signal value,
33 // a buffer of size 1 is sufficient.
34 //
35 func Notify(c chan<- os.Signal, sig ...os.Signal) {
36 if c == nil {
37 panic("os/signal: Notify using nil channel")
38 }
39
40 handlers.Lock()
41 defer handlers.Unlock()
42 if len(sig) == 0 {
43 enableSignal(nil)
44 handlers.list = append(handlers.list, handler{c: c, all: true})
45 } else {
46 for _, s := range sig {
47 // We use nil as a special wildcard value for enableSignal,
48 // so filter it out of the list of arguments. This is safe because
49 // we will never get an incoming nil signal, so discarding the
50 // registration cannot affect the observed behavior.
51 if s != nil {
52 enableSignal(s)
53 handlers.list = append(handlers.list, handler{c: c, sig: s})
54 }
55 }
56 }
57 }
58
59 func process(sig os.Signal) {
60 handlers.Lock()
61 defer handlers.Unlock()
62
63 for _, h := range handlers.list {
64 if h.all || h.sig == sig {
65 // send but do not block for it
66 select {
67 case h.c <- sig:
68 default:
69 }
70 }
71 }
72 }