kernel_keeper.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // package kernel_keeper -- сторож системных сигналов
  2. package kernel_keeper
  3. import (
  4. "context"
  5. "os"
  6. "os/signal"
  7. "sync"
  8. "syscall"
  9. . "gitp78su.ipnodns.ru/svi/kern/v3/kc/helpers"
  10. "gitp78su.ipnodns.ru/svi/kern/v3/kc/log_buf"
  11. . "gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
  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(), wg IKernelWg) *kernelKeeper {
  27. block.Lock()
  28. defer block.Unlock()
  29. if kernKeep != nil {
  30. kernKeep.log.Debug("GetKernelKeeper()")
  31. return kernKeep
  32. }
  33. Hassert(ctx != nil, "NewKernelCtx(): ctx==nil")
  34. Hassert(wg != nil, "NewKernelCtx(): IKernelWg==nil")
  35. Hassert(fnCancel != nil, "NewKernelCtx(): fnCancel==nil")
  36. sf := &kernelKeeper{
  37. ctx: ctx,
  38. fnCancel: fnCancel,
  39. wg: wg,
  40. log: log_buf.NewLogBuf(log_buf.OptIsTerm(true), log_buf.OptPrefix("kernelKeeper")),
  41. chSys_: make(chan os.Signal, 2),
  42. }
  43. sf.log.Debug("GetKernelKeeper(): first run")
  44. res := sf.wg.Add("kernel_keeper")
  45. res.Hassert("NewKernelCtx(): in add stream kernel keeper in IKernelWg")
  46. go sf.run(sf.chSys_)
  47. kernKeep = sf
  48. _ = IKernelKeeper(sf)
  49. return sf
  50. }
  51. // Log -- возвращает лог сторожа системных сигналов
  52. func (sf *kernelKeeper) Log() ILogBuf {
  53. return sf.log
  54. }
  55. // Работает в отдельном потоке и ждёт сигналов прерываний работы
  56. func (sf *kernelKeeper) run(chSys chan os.Signal) {
  57. sf.log.Debug("run()")
  58. // Регистрируем сигналы SIGINT (Ctrl+C) и SIGTERM (завершение процесса)
  59. // syscall.SIGHUP: Сигнал, отправляемый при закрытии терминала.
  60. // syscall.SIGQUIT: Сигнал, отправляемый при нажатии **Ctrl+**.
  61. signal.Notify(chSys, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
  62. select {
  63. case sig := <-chSys: // системный сигнал
  64. sf.log.Debug("run(): system signal, sig=%v\n", sig)
  65. sf.fnCancel()
  66. case <-sf.ctx.Done(): // сигнал от приложения
  67. sf.log.Debug("run(): cancel app context, err=\n\t%v\n", sf.ctx.Err())
  68. }
  69. sf.wg.Done("kernel_keeper")
  70. sf.log.Debug("run(): end")
  71. }