kernel_keeper.go 2.6 KB

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