kernel_keeper.go 2.6 KB

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