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.
4
5package main
6
7import (
8	"os"
9	"os/signal"
10)
11
12// shutdownRequestChannel is used to initiate shutdown from one of the
13// subsystems using the same code paths as when an interrupt signal is received.
14var shutdownRequestChannel = make(chan struct{})
15
16// interruptSignals defines the default signals to catch in order to do a proper
17// shutdown.  This may be modified during init depending on the platform.
18var interruptSignals = []os.Signal{os.Interrupt}
19
20// interruptListener listens for OS Signals such as SIGINT (Ctrl+C) and shutdown
21// requests from shutdownRequestChannel.  It returns a channel that is closed
22// when either signal is received.
23func interruptListener() <-chan struct{} {
24	c := make(chan struct{})
25	go func() {
26		interruptChannel := make(chan os.Signal, 1)
27		signal.Notify(interruptChannel, interruptSignals...)
28
29		// Listen for initial shutdown signal and close the returned
30		// channel to notify the caller.
31		select {
32		case sig := <-interruptChannel:
33			btcdLog.Infof("Received signal (%s).  Shutting down...",
34				sig)
35
36		case <-shutdownRequestChannel:
37			btcdLog.Info("Shutdown requested.  Shutting down...")
38		}
39		close(c)
40
41		// Listen for repeated signals and display a message so the user
42		// knows the shutdown is in progress and the process is not
43		// hung.
44		for {
45			select {
46			case sig := <-interruptChannel:
47				btcdLog.Infof("Received signal (%s).  Already "+
48					"shutting down...", sig)
49
50			case <-shutdownRequestChannel:
51				btcdLog.Info("Shutdown requested.  Already " +
52					"shutting down...")
53			}
54		}
55	}()
56
57	return c
58}
59
60// interruptRequested returns true when the channel returned by
61// interruptListener was closed.  This simplifies early shutdown slightly since
62// the caller can just use an if statement instead of a select.
63func interruptRequested(interrupted <-chan struct{}) bool {
64	select {
65	case <-interrupted:
66		return true
67	default:
68	}
69
70	return false
71}
72