kernel_keeper.go 2.7 KB

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