// Package signals catches the signals that end the tool, for the // commands that clean up before they end. package signals import ( "context" "os" "os/signal" "syscall" ) // Context is signal.NotifyContext for SIGINT, SIGTERM and SIGHUP: the // context it returns is cancelled when one of them arrives, and stop // stops catching them. It leaves out any of the three the tool was // started with set to be ignored, as nohup does with SIGHUP, because // catching a signal turns an ignored one back on and would end a run // that was meant to survive it. func Context(parent context.Context) (context.Context, context.CancelFunc) { endings := caught() // Given no signals at all, NotifyContext would catch every one. if len(endings) == 0 { return context.WithCancel(parent) } return signal.NotifyContext(parent, endings...) } // Notify is signal.Notify for the signals Context catches: each one // that arrives is sent to c, until signal.Stop(c). func Notify(c chan<- os.Signal) { endings := caught() // Given no signals at all, Notify would catch every one. if len(endings) > 0 { signal.Notify(c, endings...) } } // caught returns those of SIGINT, SIGTERM and SIGHUP that the tool was // not started with set to be ignored. func caught() []os.Signal { endings := []os.Signal{syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP} kept := make([]os.Signal, 0, len(endings)) for _, ending := range endings { if !signal.Ignored(ending) { kept = append(kept, ending) } } return kept }