From f50c960cae3fa6f17ea5c8e4e3bb50d4994cc6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= <sybren@stuvel.eu> Date: Fri, 17 Feb 2017 12:40:03 +0100 Subject: [PATCH] Manager: clean shutdown of HTTP server, requires Go 1.8+ Go 1.8 introduced a way to cleanly shut down the HTTP server. This allows us to handle any currently running requests while rejecting new ones, and then fully shut down. --- .../src/flamenco-manager/main.go | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/flamenco-manager-go/src/flamenco-manager/main.go b/packages/flamenco-manager-go/src/flamenco-manager/main.go index 6a3ae17a..47a4fdf0 100644 --- a/packages/flamenco-manager-go/src/flamenco-manager/main.go +++ b/packages/flamenco-manager-go/src/flamenco-manager/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "flag" "fmt" "net/http" @@ -30,6 +31,8 @@ var upstream *flamenco.UpstreamConnection var task_scheduler *flamenco.TaskScheduler var task_update_pusher *flamenco.TaskUpdatePusher var task_timeout_checker *flamenco.TaskTimeoutChecker +var httpServer *http.Server +var shutdownComplete chan struct{} func http_status(w http.ResponseWriter, r *http.Request) { flamenco.SendStatusReport(w, r, session, FLAMENCO_VERSION) @@ -113,6 +116,14 @@ func shutdown(signum os.Signal) { go func() { log.Infof("Signal '%s' received, shutting down.", signum) + + if httpServer != nil { + log.Info("Shutting down HTTP server") + httpServer.Shutdown(context.Background()) + } else { + log.Warning("HTTP server was not even started yet") + } + task_timeout_checker.Close() task_update_pusher.Close() upstream.Close() @@ -124,8 +135,9 @@ func shutdown(signum os.Signal) { log.Error("Shutdown forced, stopping process.") os.Exit(-2) } + log.Warning("Shutdown complete, stopping process.") - os.Exit(0) + close(shutdownComplete) } var cliArgs struct { @@ -224,6 +236,12 @@ func main() { go task_update_pusher.Go() go task_timeout_checker.Go() + // Create the HTTP server before allowing the shutdown signal Handler + // to exist. This prevents a race condition when Ctrl+C is pressed after + // the http.Server is created, but before it is assigned to httpServer. + httpServer = &http.Server{Addr: config.Listen, Handler: router} + shutdownComplete = make(chan struct{}) + // Handle Ctrl+C c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) @@ -237,12 +255,10 @@ func main() { // Fall back to insecure server if TLS certificate/key is not defined. if !has_tls { - log.Fatal(http.ListenAndServe(config.Listen, router)) + log.Warning(httpServer.ListenAndServe()) } else { - log.Fatal(http.ListenAndServeTLS( - config.Listen, - config.TLSCert, - config.TLSKey, - router)) + log.Warning(httpServer.ListenAndServeTLS(config.TLSCert, config.TLSKey)) } + + <-shutdownComplete } -- GitLab