signalutils.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package signalutils
  15. import (
  16. "os"
  17. "os/signal"
  18. "runtime/debug"
  19. "sync"
  20. "yunion.io/x/log"
  21. )
  22. type SSignalManager struct {
  23. sig chan os.Signal
  24. traps map[os.Signal]Trap
  25. mtx *sync.RWMutex
  26. started bool
  27. }
  28. var signalManager *SSignalManager
  29. type Trap func()
  30. func RegisterSignal(trap Trap, sigs ...os.Signal) {
  31. signalManager.mtx.Lock()
  32. defer signalManager.mtx.Unlock()
  33. if !signalManager.started {
  34. for i := 0; i < len(sigs); i++ {
  35. signalManager.traps[sigs[i]] = trap
  36. }
  37. } else {
  38. for i := 0; i < len(sigs); i++ {
  39. signalManager.traps[sigs[i]] = trap
  40. signal.Notify(signalManager.sig, sigs[i])
  41. }
  42. }
  43. }
  44. func StartTrap() {
  45. if signalManager.started {
  46. return
  47. } else {
  48. signalManager.started = true
  49. }
  50. for sig, _ := range signalManager.traps {
  51. signal.Notify(signalManager.sig, sig)
  52. }
  53. go func() {
  54. defer func() {
  55. if err := recover(); err != nil {
  56. log.Errorf("Call trap func error: %#v", err)
  57. debug.PrintStack()
  58. }
  59. }()
  60. signalManager.mtx.RLock()
  61. defer signalManager.mtx.RUnlock()
  62. for {
  63. s := <-signalManager.sig
  64. trapFunc := signalManager.traps[s]
  65. trapFunc()
  66. }
  67. }()
  68. }
  69. func init() {
  70. signalManager = &SSignalManager{
  71. sig: make(chan os.Signal, 1),
  72. traps: make(map[os.Signal]Trap, 0),
  73. mtx: &sync.RWMutex{},
  74. }
  75. }