gproc_signal.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gproc
  7. import (
  8. "context"
  9. "github.com/gogf/gf/internal/intlog"
  10. "os"
  11. "os/signal"
  12. "sync"
  13. "syscall"
  14. )
  15. // SigHandler defines a function type for signal handling.
  16. type SigHandler func(sig os.Signal)
  17. var (
  18. signalHandlerMap = make(map[os.Signal][]SigHandler)
  19. shutdownSignalMap = map[os.Signal]struct{}{
  20. syscall.SIGINT: {},
  21. syscall.SIGQUIT: {},
  22. syscall.SIGKILL: {},
  23. syscall.SIGTERM: {},
  24. syscall.SIGABRT: {},
  25. }
  26. )
  27. func init() {
  28. for sig, _ := range shutdownSignalMap {
  29. signalHandlerMap[sig] = make([]SigHandler, 0)
  30. }
  31. }
  32. // AddSigHandler adds custom signal handler for custom one or more signals.
  33. func AddSigHandler(handler SigHandler, signals ...os.Signal) {
  34. for _, sig := range signals {
  35. signalHandlerMap[sig] = append(signalHandlerMap[sig], handler)
  36. }
  37. }
  38. // AddSigHandlerShutdown adds custom signal handler for shutdown signals:
  39. // syscall.SIGINT,
  40. // syscall.SIGQUIT,
  41. // syscall.SIGKILL,
  42. // syscall.SIGTERM,
  43. // syscall.SIGABRT.
  44. func AddSigHandlerShutdown(handler ...SigHandler) {
  45. for _, h := range handler {
  46. for sig, _ := range shutdownSignalMap {
  47. signalHandlerMap[sig] = append(signalHandlerMap[sig], h)
  48. }
  49. }
  50. }
  51. // Listen blocks and does signal listening and handling.
  52. func Listen() {
  53. signals := make([]os.Signal, 0)
  54. for sig, _ := range signalHandlerMap {
  55. signals = append(signals, sig)
  56. }
  57. sigChan := make(chan os.Signal, 1)
  58. signal.Notify(sigChan, signals...)
  59. var sig os.Signal
  60. for {
  61. wg := sync.WaitGroup{}
  62. sig = <-sigChan
  63. intlog.Printf(context.TODO(), `signal received: %s`, sig.String())
  64. if handlers, ok := signalHandlerMap[sig]; ok {
  65. for _, handler := range handlers {
  66. wg.Add(1)
  67. go func(handler SigHandler, sig os.Signal) {
  68. defer wg.Done()
  69. handler(sig)
  70. }(handler, sig)
  71. }
  72. }
  73. // If it is shutdown signal, it exits this signal listening.
  74. if _, ok := shutdownSignalMap[sig]; ok {
  75. // Wait until signal handlers done.
  76. wg.Wait()
  77. return
  78. }
  79. }
  80. }