src/pkg/os/signal/signal.go - The Go Programming Language

Golang

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	}