1 // Copyright (c) 2013-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
12 // interruptChannel is used to receive SIGINT (Ctrl+C) signals.
13 var interruptChannel chan os.Signal
15 // addHandlerChannel is used to add an interrupt handler to the list of handlers
16 // to be invoked on SIGINT (Ctrl+C) signals.
17 var addHandlerChannel = make(chan func())
19 // mainInterruptHandler listens for SIGINT (Ctrl+C) signals on the
20 // interruptChannel and invokes the registered interruptCallbacks accordingly.
21 // It also listens for callback registration. It must be run as a goroutine.
22 func mainInterruptHandler() {
23 // interruptCallbacks is a list of callbacks to invoke when a
24 // SIGINT (Ctrl+C) is received.
25 var interruptCallbacks []func()
27 // isShutdown is a flag which is used to indicate whether or not
28 // the shutdown signal has already been received and hence any future
29 // attempts to add a new interrupt handler should invoke them
35 case <-interruptChannel:
36 // Ignore more than one shutdown signal.
38 log.Infof("Received SIGINT (Ctrl+C). " +
39 "Already shutting down...")
44 log.Infof("Received SIGINT (Ctrl+C). Shutting down...")
46 // Run handlers in LIFO order.
47 for i := range interruptCallbacks {
48 idx := len(interruptCallbacks) - 1 - i
49 callback := interruptCallbacks[idx]
53 // Signal the main goroutine to shutdown.
55 shutdownChannel <- nil
58 case handler := <-addHandlerChannel:
59 // The shutdown signal has already been received, so
60 // just invoke and new handlers immediately.
65 interruptCallbacks = append(interruptCallbacks, handler)
70 // addInterruptHandler adds a handler to call when a SIGINT (Ctrl+C) is
72 func addInterruptHandler(handler func()) {
73 // Create the channel and start the main interrupt handler which invokes
74 // all other callbacks and exits if not already done.
75 if interruptChannel == nil {
76 interruptChannel = make(chan os.Signal, 1)
77 signal.Notify(interruptChannel, os.Interrupt)
78 go mainInterruptHandler()
81 addHandlerChannel <- handler