// Package atexit provides handling for functions you want called when // the program exits unexpectedly due to a signal. // // You should also make sure you call Run in the normal exit path. package atexit import ( "os" "os/signal" "sync" "github.com/ncw/rclone/fs" ) var ( fns []func() exitChan chan os.Signal exitOnce sync.Once registerOnce sync.Once ) // Register a function to be called on exit func Register(fn func()) { fns = append(fns, fn) // Run AtExit handlers on SIGINT or SIGTERM so everything gets // tidied up properly registerOnce.Do(func() { exitChan = make(chan os.Signal, 1) signal.Notify(exitChan, os.Interrupt) // syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT go func() { sig, closed := <-exitChan if closed || sig == nil { return } fs.Infof(nil, "Signal received: %s", sig) Run() fs.Infof(nil, "Exiting...") os.Exit(0) }() }) } // IgnoreSignals disables the signal handler and prevents Run from beeing executed automatically func IgnoreSignals() { registerOnce.Do(func() {}) if exitChan != nil { signal.Stop(exitChan) close(exitChan) exitChan = nil } } // Run all the at exit functions if they haven't been run already func Run() { exitOnce.Do(func() { for _, fn := range fns { fn() } }) }