kernel_keeper.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // package kernel_keeper -- сторож системных сигналов
  2. package kernel_keeper
  3. import (
  4. "context"
  5. "fmt"
  6. "os"
  7. "os/signal"
  8. "sync"
  9. "syscall"
  10. . "gitp78su.ipnodns.ru/svi/kern/v4/lev0/ktypes"
  11. . "gitp78su.ipnodns.ru/svi/kern/v4/lev1"
  12. )
  13. // kernelKeeper -- сторож системных сигналов
  14. type kernelKeeper struct {
  15. ctx context.Context
  16. fnCancel func()
  17. wg IKernelWg
  18. log ILogBuf
  19. chSys_ chan os.Signal
  20. }
  21. var (
  22. kernKeep *kernelKeeper
  23. block sync.Mutex
  24. )
  25. // GetKernelKeeper -- возвращает новый сторож системных сигналов
  26. func GetKernelKeeper(ctx context.Context, fnCancel func(),
  27. wg IKernelWg) IResult[*kernelKeeper] {
  28. block.Lock()
  29. defer block.Unlock()
  30. if kernKeep != nil {
  31. kernKeep.log.Debug("GetKernelKeeper()")
  32. return NewRes(kernKeep)
  33. }
  34. if ctx == nil {
  35. err := fmt.Errorf("NewKernelCtx(): ctx==nil")
  36. return NewErr[*kernelKeeper](err)
  37. }
  38. if wg == nil {
  39. err := fmt.Errorf("NewKernelCtx(): IKernelWg==nil")
  40. return NewErr[*kernelKeeper](err)
  41. }
  42. if fnCancel == nil {
  43. err := fmt.Errorf("NewKernelCtx(): fnCancel==nil")
  44. return NewErr[*kernelKeeper](err)
  45. }
  46. sf := &kernelKeeper{
  47. ctx: ctx,
  48. fnCancel: fnCancel,
  49. wg: wg,
  50. log: NewLogBuf(OptIsTerm(true), OptPrefix("kernelKeeper")),
  51. chSys_: make(chan os.Signal, 2),
  52. }
  53. sf.log.Debug("GetKernelKeeper(): first run")
  54. res := sf.wg.Add("kernel_keeper")
  55. res.Hassert("NewKernelCtx(): in add stream kernel keeper in IKernelWg")
  56. go sf.run(sf.chSys_)
  57. kernKeep = sf
  58. _ = IKernelKeeper(sf)
  59. return NewRes(sf)
  60. }
  61. // Log -- возвращает лог сторожа системных сигналов
  62. func (sf *kernelKeeper) Log() ILogBuf {
  63. return sf.log
  64. }
  65. // Работает в отдельном потоке и ждёт сигналов прерываний работы
  66. func (sf *kernelKeeper) run(chSys chan os.Signal) {
  67. sf.log.Debug("run()")
  68. // Регистрируем сигналы SIGINT (Ctrl+C) и SIGTERM (завершение процесса)
  69. // syscall.SIGHUP: Сигнал, отправляемый при закрытии терминала.
  70. // syscall.SIGQUIT: Сигнал, отправляемый при нажатии **Ctrl+**.
  71. signal.Notify(chSys, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
  72. select {
  73. case sig := <-chSys: // системный сигнал
  74. sf.log.Debug("run(): system signal, sig=%v\n", sig)
  75. sf.fnCancel()
  76. case <-sf.ctx.Done(): // сигнал от приложения
  77. sf.log.Debug("run(): cancel app context, err=\n\t%v\n", sf.ctx.Err())
  78. }
  79. sf.wg.Done("kernel_keeper")
  80. sf.log.Debug("run(): end")
  81. }