| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package signal implements access to incoming signals. |
| package signal |
| |
| // BUG(rsc): This package is not yet implemented on Plan 9 and Windows. |
| |
| import ( |
| "os" |
| "sync" |
| ) |
| |
| var handlers struct { |
| sync.Mutex |
| list []handler |
| } |
| |
| type handler struct { |
| c chan<- os.Signal |
| sig os.Signal |
| all bool |
| } |
| |
| // Notify causes package signal to relay incoming signals to c. |
| // If no signals are listed, all incoming signals will be relayed to c. |
| // Otherwise, just the listed signals will. |
| // |
| // Package signal will not block sending to c: the caller must ensure |
| // that c has sufficient buffer space to keep up with the expected |
| // signal rate. For a channel used for notification of just one signal value, |
| // a buffer of size 1 is sufficient. |
| // |
| func Notify(c chan<- os.Signal, sig ...os.Signal) { |
| if c == nil { |
| panic("os/signal: Notify using nil channel") |
| } |
| |
| handlers.Lock() |
| defer handlers.Unlock() |
| if len(sig) == 0 { |
| enableSignal(nil) |
| handlers.list = append(handlers.list, handler{c: c, all: true}) |
| } else { |
| for _, s := range sig { |
| // We use nil as a special wildcard value for enableSignal, |
| // so filter it out of the list of arguments. This is safe because |
| // we will never get an incoming nil signal, so discarding the |
| // registration cannot affect the observed behavior. |
| if s != nil { |
| enableSignal(s) |
| handlers.list = append(handlers.list, handler{c: c, sig: s}) |
| } |
| } |
| } |
| } |
| |
| func process(sig os.Signal) { |
| handlers.Lock() |
| defer handlers.Unlock() |
| |
| for _, h := range handlers.list { |
| if h.all || h.sig == sig { |
| // send but do not block for it |
| select { |
| case h.c <- sig: |
| default: |
| } |
| } |
| } |
| } |