kernel_keeper.go 2.8 KB

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