signal.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Copyright (c) 2013-2016 The btcsuite developers
  2. // Copyright (c) 2019 Caleb James DeLisle
  3. // Use of this source code is governed by an ISC
  4. // license that can be found in the LICENSE file.
  5. package main
  6. import (
  7. "os"
  8. "os/signal"
  9. "runtime"
  10. "github.com/pkt-cash/pktd/pktlog/log"
  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.
  14. var shutdownRequestChannel = make(chan struct{})
  15. // interruptSignals defines the default signals to catch in order to do a proper
  16. // shutdown. This may be modified during init depending on the platform.
  17. var interruptSignals = []os.Signal{os.Interrupt}
  18. // interruptListener listens for OS Signals such as SIGINT (Ctrl+C) and shutdown
  19. // requests from shutdownRequestChannel. It returns a channel that is closed
  20. // when either signal is received.
  21. func interruptListener() <-chan struct{} {
  22. c := make(chan struct{})
  23. go func() {
  24. interruptChannel := make(chan os.Signal, 1)
  25. signal.Notify(interruptChannel, interruptSignals...)
  26. // Listen for initial shutdown signal and close the returned
  27. // channel to notify the caller.
  28. select {
  29. case sig := <-interruptChannel:
  30. log.Infof("Received signal (%s). Shutting down...",
  31. sig)
  32. case <-shutdownRequestChannel:
  33. log.Info("Shutdown requested. Shutting down...")
  34. }
  35. close(c)
  36. // Listen for repeated signals and display a message so the user
  37. // knows the shutdown is in progress and the process is not
  38. // hung.
  39. for {
  40. select {
  41. case sig := <-interruptChannel:
  42. log.Infof("Received signal (%s). Already "+
  43. "shutting down...", sig)
  44. buf := make([]byte, 1<<20)
  45. stacklen := runtime.Stack(buf, true)
  46. log.Infof("*** goroutine dump...\n%s\n*** end\n", buf[:stacklen])
  47. case <-shutdownRequestChannel:
  48. log.Info("Shutdown requested. Already " +
  49. "shutting down...")
  50. }
  51. }
  52. }()
  53. return c
  54. }
  55. // interruptRequested returns true when the channel returned by
  56. // interruptListener was closed. This simplifies early shutdown slightly since
  57. // the caller can just use an if statement instead of a select.
  58. func interruptRequested(interrupted <-chan struct{}) bool {
  59. select {
  60. case <-interrupted:
  61. return true
  62. default:
  63. }
  64. return false
  65. }