diff options
Diffstat (limited to 'core/sigtrap.go')
-rw-r--r-- | core/sigtrap.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/core/sigtrap.go b/core/sigtrap.go new file mode 100644 index 000000000..3b74efb02 --- /dev/null +++ b/core/sigtrap.go @@ -0,0 +1,71 @@ +package core + +import ( + "log" + "os" + "os/signal" + "sync" + + "github.com/miekg/coredns/server" +) + +// TrapSignals create signal handlers for all applicable signals for this +// system. If your Go program uses signals, this is a rather invasive +// function; best to implement them yourself in that case. Signals are not +// required for the caddy package to function properly, but this is a +// convenient way to allow the user to control this package of your program. +func TrapSignals() { + trapSignalsCrossPlatform() + trapSignalsPosix() +} + +// trapSignalsCrossPlatform captures SIGINT, which triggers forceful +// shutdown that executes shutdown callbacks first. A second interrupt +// signal will exit the process immediately. +func trapSignalsCrossPlatform() { + go func() { + shutdown := make(chan os.Signal, 1) + signal.Notify(shutdown, os.Interrupt) + + for i := 0; true; i++ { + <-shutdown + + if i > 0 { + log.Println("[INFO] SIGINT: Force quit") + if PidFile != "" { + os.Remove(PidFile) + } + os.Exit(1) + } + + log.Println("[INFO] SIGINT: Shutting down") + + if PidFile != "" { + os.Remove(PidFile) + } + + go os.Exit(executeShutdownCallbacks("SIGINT")) + } + }() +} + +// executeShutdownCallbacks executes the shutdown callbacks as initiated +// by signame. It logs any errors and returns the recommended exit status. +// This function is idempotent; subsequent invocations always return 0. +func executeShutdownCallbacks(signame string) (exitCode int) { + shutdownCallbacksOnce.Do(func() { + serversMu.Lock() + errs := server.ShutdownCallbacks(servers) + serversMu.Unlock() + + if len(errs) > 0 { + for _, err := range errs { + log.Printf("[ERROR] %s shutdown: %v", signame, err) + } + exitCode = 1 + } + }) + return +} + +var shutdownCallbacksOnce sync.Once |