signal_handling.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. //go:build !plan9
  2. // +build !plan9
  3. package grace
  4. import (
  5. "github.com/seaweedfs/seaweedfs/weed/glog"
  6. "os"
  7. "os/signal"
  8. "reflect"
  9. "runtime"
  10. "sync"
  11. "syscall"
  12. )
  13. var signalChan chan os.Signal
  14. var interruptHooks = make([]func(), 0)
  15. var interruptHookLock sync.RWMutex
  16. var reloadHooks = make([]func(), 0)
  17. var reloadHookLock sync.RWMutex
  18. func GetFunctionName(i interface{}) string {
  19. return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
  20. }
  21. func init() {
  22. signalChan = make(chan os.Signal, 1)
  23. signal.Notify(signalChan,
  24. os.Interrupt,
  25. os.Kill,
  26. syscall.SIGALRM,
  27. syscall.SIGHUP,
  28. syscall.SIGINT,
  29. syscall.SIGTERM,
  30. // syscall.SIGQUIT,
  31. )
  32. go func() {
  33. for s := range signalChan {
  34. if s.String() == syscall.SIGHUP.String() {
  35. reloadHookLock.RLock()
  36. for _, hook := range reloadHooks {
  37. hook()
  38. }
  39. reloadHookLock.RUnlock()
  40. } else {
  41. interruptHookLock.RLock()
  42. for _, hook := range interruptHooks {
  43. glog.V(4).Infof("exec interrupt hook func name:%s", GetFunctionName(hook))
  44. hook()
  45. }
  46. interruptHookLock.RUnlock()
  47. os.Exit(0)
  48. }
  49. }
  50. }()
  51. }
  52. func OnReload(fn func()) {
  53. // prevent reentry
  54. reloadHookLock.Lock()
  55. defer reloadHookLock.Unlock()
  56. reloadHooks = append(reloadHooks, fn)
  57. }
  58. func OnInterrupt(fn func()) {
  59. // prevent reentry
  60. interruptHookLock.Lock()
  61. defer interruptHookLock.Unlock()
  62. // deal with control+c,etc
  63. // controlling terminal close, daemon not exit
  64. interruptHooks = append(interruptHooks, fn)
  65. }