diff options
Diffstat (limited to 'src/pkg/os/signal/signal.go')
| -rw-r--r-- | src/pkg/os/signal/signal.go | 77 |
1 files changed, 56 insertions, 21 deletions
diff --git a/src/pkg/os/signal/signal.go b/src/pkg/os/signal/signal.go index bce4530e7..dfdcf4061 100644 --- a/src/pkg/os/signal/signal.go +++ b/src/pkg/os/signal/signal.go @@ -1,37 +1,72 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// 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. -// +build darwin freebsd linux netbsd openbsd - -// Package signal implements operating system-independent signal handling. +// Package signal implements access to incoming signals. package signal +// BUG(rsc): This package is not yet implemented on Plan 9 and Windows. + import ( "os" - "runtime" + "sync" ) -// Incoming is the global signal channel. -// All signals received by the program will be delivered to this channel. -var Incoming <-chan os.Signal +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") + } -func process(ch chan<- os.Signal) { - for { - var mask uint32 = runtime.Sigrecv() - for sig := uint(0); sig < 32; sig++ { - if mask&(1<<sig) != 0 { - ch <- os.UnixSignal(sig) + 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 init() { - runtime.Siginit() - ch := make(chan os.Signal) // Done here so Incoming can have type <-chan Signal - Incoming = ch - go process(ch) -} +func process(sig os.Signal) { + handlers.Lock() + defer handlers.Unlock() -// BUG(rsc): This package is unavailable on Plan 9 and Windows. + for _, h := range handlers.list { + if h.all || h.sig == sig { + // send but do not block for it + select { + case h.c <- sig: + default: + } + } + } +} |
