kernel_keeper.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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/d0"
  10. "gitp78su.ipnodns.ru/svi/kern/v4/d1"
  11. "gitp78su.ipnodns.ru/svi/kern/v4/d2/kern_ent/stream_name"
  12. "gitp78su.ipnodns.ru/svi/kern/v4/d2/kspec"
  13. )
  14. // KernKeeper -- сторож системных сигналов.
  15. type KernKeeper struct {
  16. owner *d0.LOwner
  17. ctx context.Context
  18. fnCancel func()
  19. wg kspec.IKernelWg
  20. log *d1.LogBuf
  21. chSys_ chan os.Signal
  22. }
  23. var (
  24. kernKeep *KernKeeper
  25. block sync.Mutex
  26. qName = stream_name.NewAStreamName("kernel_keeper")
  27. )
  28. // GetKernelKeeper -- возвращает новый сторож системных сигналов.
  29. func GetKernelKeeper(ctx context.Context, fnCancel func(),
  30. wg kspec.IKernelWg) *KernKeeper {
  31. block.Lock()
  32. defer block.Unlock()
  33. if kernKeep != nil {
  34. kernKeep.log.Debug("GetKernelKeeper()")
  35. return kernKeep
  36. }
  37. d0.If(ctx == nil).Hassert("NewKernelCtx(): ctx==nil", []any{})
  38. d0.If(wg == nil).Hassert("NewKernelCtx(): IKernelWg==nil", []any{})
  39. d0.If(fnCancel == nil).Hassert("NewKernelCtx(): fnCancel==nil", []any{})
  40. owner := d0.LetOwner(1, "kern_keeper")
  41. paramLogBuf := &d1.LogBufParam{
  42. IsTerm_: d0.MutSafeBool(owner, true),
  43. Prefix_: d0.LetTxt("kernelKeeper"),
  44. }
  45. sf := &KernKeeper{
  46. owner: owner,
  47. ctx: ctx,
  48. fnCancel: fnCancel,
  49. wg: wg,
  50. log: d1.NewLogBuf(paramLogBuf),
  51. chSys_: make(chan os.Signal, 2),
  52. }
  53. sf.log.Debug("GetKernelKeeper(): first run")
  54. sf.wg.Add(qName)
  55. go sf.run(sf.chSys_)
  56. kernKeep = sf
  57. return sf
  58. }
  59. // Log -- возвращает лог сторожа системных сигналов.
  60. func (sf *KernKeeper) Log() *d1.LogBuf {
  61. return sf.log
  62. }
  63. // Работает в отдельном потоке и ждёт сигналов прерываний работы.
  64. func (sf *KernKeeper) 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. }