// package kernel_keeper -- сторож системных сигналов. package kernel_keeper import ( "context" "os" "os/signal" "sync" "syscall" "gitp78su.ipnodns.ru/svi/kern/v4/lev0/defs" "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers" mL1 "gitp78su.ipnodns.ru/svi/kern/v4/lev1" "gitp78su.ipnodns.ru/svi/kern/v4/lev1/comp_spec" "gitp78su.ipnodns.ru/svi/kern/v4/lev1/safe_bool" "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kern_ent/stream_name" "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kspec" ) // kernelKeeper -- сторож системных сигналов. type kernelKeeper struct { ctx context.Context fnCancel func() wg kspec.IKernelWg log comp_spec.ILogBuf chSys_ chan os.Signal } var ( kernKeep *kernelKeeper block sync.Mutex qName = stream_name.NewAStreamName(defs.TxtFix("kernel_keeper")) ) // GetKernelKeeper -- возвращает новый сторож системных сигналов. func GetKernelKeeper(ctx context.Context, fnCancel func(), wg kspec.IKernelWg) *kernelKeeper { block.Lock() defer block.Unlock() if kernKeep != nil { kernKeep.log.Debug(defs.TxtFix("GetKernelKeeper()")) return kernKeep } helpers.If(ctx == nil).Hassert("NewKernelCtx(): ctx==nil", []any{}) helpers.If(wg == nil).Hassert("NewKernelCtx(): IKernelWg==nil", []any{}) helpers.If(fnCancel == nil).Hassert("NewKernelCtx(): fnCancel==nil", []any{}) paramLogBuf := &mL1.LogBufParam{ IsTerm_: safe_bool.NewSafeBool(true), Prefix_: defs.TxtFix("kernelKeeper"), } sf := &kernelKeeper{ ctx: ctx, fnCancel: fnCancel, wg: wg, log: mL1.NewLogBuf(paramLogBuf), chSys_: make(chan os.Signal, 2), } sf.log.Debug(defs.TxtFix("GetKernelKeeper(): first run")) sf.wg.Add(qName) go sf.run(sf.chSys_) kernKeep = sf _ = kspec.IKernelKeeper(sf) return sf } // Log -- возвращает лог сторожа системных сигналов. func (sf *kernelKeeper) Log() comp_spec.ILogBuf { return sf.log } // Работает в отдельном потоке и ждёт сигналов прерываний работы. func (sf *kernelKeeper) run(chSys chan os.Signal) { sf.log.Debug(defs.TxtFix("run()")) // Регистрируем сигналы SIGINT (Ctrl+C) и SIGTERM (завершение процесса) // syscall.SIGHUP: Сигнал, отправляемый при закрытии терминала. // syscall.SIGQUIT: Сигнал, отправляемый при нажатии **Ctrl+**. signal.Notify(chSys, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT) select { case sig := <-chSys: // системный сигнал sf.log.Debug(defs.TxtFix("run(): system signal, sig=%v\n"), sig) sf.fnCancel() case <-sf.ctx.Done(): // сигнал от приложения sf.log.Debug(defs.TxtFix("run(): cancel app context, err=\n\t%v\n"), sf.ctx.Err()) } sf.wg.Done(qName) sf.log.Debug(defs.TxtFix("run(): end")) }