diff --git a/common/signals.go b/common/signals.go new file mode 100644 index 00000000..067bf340 --- /dev/null +++ b/common/signals.go @@ -0,0 +1,38 @@ +package common + +import ( + "os" + "os/signal" + "runtime" + "syscall" +) + +// A subsystem/server/... that can be stopped or queried about the status with a signal +type SignalsReceiver interface { + Status() string + Stop() error +} + +func SignalHandlerLoop(ss ...SignalsReceiver) { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGUSR1) + buf := make([]byte, 1<<20) + for { + sig := <-sigs + switch sig { + case syscall.SIGINT: + Info.Printf("=== received SIGINT ===\n*** exiting\n") + for _, subsystem := range ss { + subsystem.Stop() + } + os.Exit(0) + case syscall.SIGQUIT: + stacklen := runtime.Stack(buf, true) + Info.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen]) + case syscall.SIGUSR1: + for _, subsystem := range ss { + Info.Printf("=== received SIGUSR1 ===\n*** status...\n%s\n*** end\n", subsystem.Status()) + } + } + } +} diff --git a/router/router.go b/router/router.go index 63f0641f..f6118761 100644 --- a/router/router.go +++ b/router/router.go @@ -94,6 +94,11 @@ func (router *Router) Start() { } } +func (router *Router) Stop() error { + // TODO: perform greceful shutdown... + return nil +} + func (router *Router) UsingPassword() bool { return router.Password != nil } diff --git a/weavedns/main.go b/weavedns/main.go index ae1e06e8..6a888896 100644 --- a/weavedns/main.go +++ b/weavedns/main.go @@ -9,9 +9,6 @@ import ( weavenet "github.com/weaveworks/weave/net" "net" "os" - "os/signal" - "runtime" - "syscall" ) var version = "(unreleased version)" @@ -90,30 +87,11 @@ func main() { } Info.Println("Upstream", srv.Upstream) - Debug.Printf("Starting the signals handler") - go handleSignals(srv) - + go SignalHandlerLoop(srv) go weavedns.ListenHTTP(version, srv, domain, zone, httpPort) + err = srv.Start() if err != nil { - Error.Fatal("Failed to start the WeaveDNS server", err) - } -} - -func handleSignals(s *weavedns.DNSServer) { - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGQUIT) - buf := make([]byte, 1<<20) - for { - sig := <-sigs - switch sig { - case syscall.SIGINT: - Info.Printf("=== received SIGINT ===\n*** exiting\n") - s.Stop() - os.Exit(0) - case syscall.SIGQUIT: - stacklen := runtime.Stack(buf, true) - Info.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen]) - } + Error.Fatal("[main] Failed to start the WeaveDNS server: ", err) } } diff --git a/weaver/main.go b/weaver/main.go index 614d1db7..12335c57 100644 --- a/weaver/main.go +++ b/weaver/main.go @@ -7,16 +7,15 @@ import ( "fmt" "github.com/davecheney/profile" "github.com/gorilla/mux" + . "github.com/weaveworks/weave/common" weavenet "github.com/weaveworks/weave/net" weave "github.com/weaveworks/weave/router" "log" "net" "net/http" "os" - "os/signal" "runtime" "strings" - "syscall" ) var version = "(unreleased version)" @@ -126,7 +125,8 @@ func main() { if httpAddr != "" { go handleHTTP(router, httpAddr) } - handleSignals(router) + + SignalHandlerLoop(router) } func options() map[string]string { @@ -209,19 +209,3 @@ func handleHTTP(router *weave.Router, httpAddr string) { log.Fatal("Unable to create http server", err) } } - -func handleSignals(router *weave.Router) { - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGQUIT, syscall.SIGUSR1) - buf := make([]byte, 1<<20) - for { - sig := <-sigs - switch sig { - case syscall.SIGQUIT: - stacklen := runtime.Stack(buf, true) - log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen]) - case syscall.SIGUSR1: - log.Printf("=== received SIGUSR1 ===\n*** status...\n%s\n*** end\n", router.Status()) - } - } -}