diff options
author | Matthew Holt <[email protected]> | 2019-07-12 10:07:11 -0600 |
---|---|---|
committer | Matthew Holt <[email protected]> | 2019-07-12 10:07:11 -0600 |
commit | b780f0f49b191a6724b7ec54aa62a97d23977231 (patch) | |
tree | 984a9f1f816fd9a092f0bba63a38c3099c43b7b1 /sigtrap.go | |
parent | 2141626269201d902b736711a808098e6d175cbb (diff) | |
download | caddy-b780f0f49b191a6724b7ec54aa62a97d23977231.tar.gz caddy-b780f0f49b191a6724b7ec54aa62a97d23977231.zip |
Standardize exit codes and improve shutdown handling; update gitignore
Diffstat (limited to 'sigtrap.go')
-rw-r--r-- | sigtrap.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/sigtrap.go b/sigtrap.go new file mode 100644 index 000000000..65f1e964f --- /dev/null +++ b/sigtrap.go @@ -0,0 +1,82 @@ +// Copyright 2015 Matthew Holt and The Caddy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package caddy + +import ( + "log" + "os" + "os/signal" + + "github.com/mholt/certmagic" +) + +// TrapSignals create signal/interrupt handlers as best it can for the +// current OS. This is a rather invasive function to call in a Go program +// that captures signals already, so in that case it would be better to +// implement these handlers yourself. +func TrapSignals() { + trapSignalsCrossPlatform() + trapSignalsPosix() +} + +// trapSignalsCrossPlatform captures SIGINT or interrupt (depending +// on the OS), which initiates a graceful shutdown. A second SIGINT +// or interrupt will forcefully 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") + os.Exit(ExitCodeForceQuit) + } + + log.Println("[INFO] SIGINT: Shutting down") + go gracefulStop("SIGINT") + } + }() +} + +// gracefulStop exits the process as gracefully as possible. +func gracefulStop(sigName string) { + exitCode := ExitCodeSuccess + + // first stop all the apps + err := Stop() + if err != nil { + log.Printf("[ERROR] %s stop: %v", sigName, err) + exitCode = ExitCodeFailedQuit + } + + // always, always, always try to clean up locks + certmagic.CleanUpOwnLocks() + + log.Printf("[INFO] %s: Shutdown done", sigName) + os.Exit(exitCode) +} + +// Exit codes. Generally, you will want to avoid +// automatically restarting the process if the +// exit code is 1. +const ( + ExitCodeSuccess = iota + ExitCodeFailedStartup + ExitCodeForceQuit + ExitCodeFailedQuit +) |