From 7b686c110342238269a8f209896042c1c8cc019e Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Mon, 14 Dec 2015 09:57:49 +0100 Subject: [PATCH] Implement signal handling With this change, the behavior is as follows: - SIGTERM / SIGINT: Exit cleanly (exit code 0) - SIGHUP: Restart This is the case both when hitting the monitor process or the inner process, or if running with NORESTART (but then we won't restart, obviously, just exit with code exitRestarting). It enables "pkill -HUP syncthing" to do the right thing to restart all Syncthings on package upgrade, for example. --- cmd/syncthing/main.go | 26 ++++++++++++++++++++++++++ cmd/syncthing/monitor.go | 16 ++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index eee1606fd..fad6cb3cb 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -19,6 +19,7 @@ import ( _ "net/http/pprof" "net/url" "os" + "os/signal" "path/filepath" "regexp" "runtime" @@ -26,6 +27,7 @@ import ( "sort" "strconv" "strings" + "syscall" "time" "github.com/syncthing/syncthing/lib/config" @@ -462,6 +464,8 @@ func upgradeViaRest() error { } func syncthingMain() { + setupSignalHandling() + // Create a main service manager. We'll add things to this as we go along. // We want any logging it does to go through our log system. mainSvc := suture.New("main", suture.Spec{ @@ -839,6 +843,28 @@ func syncthingMain() { os.Exit(code) } +func setupSignalHandling() { + // Exit cleanly with "restarting" code on SIGHUP. + + restartSign := make(chan os.Signal, 1) + sigHup := syscall.Signal(1) + signal.Notify(restartSign, sigHup) + go func() { + <-restartSign + stop <- exitRestarting + }() + + // Exit with "success" code (no restart) on INT/TERM + + stopSign := make(chan os.Signal, 1) + sigTerm := syscall.Signal(15) + signal.Notify(stopSign, os.Interrupt, sigTerm) + go func() { + <-stopSign + stop <- exitSuccess + }() +} + // printHashRate prints the hashing performance in MB/s, formatting it with // appropriate precision for the value, i.e. 182 MB/s, 18 MB/s, 1.8 MB/s, 0.18 // MB/s. diff --git a/cmd/syncthing/monitor.go b/cmd/syncthing/monitor.go index c521dba55..b56bb2bee 100644 --- a/cmd/syncthing/monitor.go +++ b/cmd/syncthing/monitor.go @@ -62,9 +62,12 @@ func monitorMain() { args := os.Args var restarts [countRestarts]time.Time - sign := make(chan os.Signal, 1) - sigTerm := syscall.Signal(0xf) - signal.Notify(sign, os.Interrupt, sigTerm, os.Kill) + stopSign := make(chan os.Signal, 1) + sigTerm := syscall.Signal(15) + signal.Notify(stopSign, os.Interrupt, sigTerm) + restartSign := make(chan os.Signal, 1) + sigHup := syscall.Signal(1) + signal.Notify(restartSign, sigHup) for { if t := time.Since(restarts[0]); t < loopThreshold { @@ -124,12 +127,17 @@ func monitorMain() { }() select { - case s := <-sign: + case s := <-stopSign: l.Infof("Signal %d received; exiting", s) cmd.Process.Kill() <-exit return + case s := <-restartSign: + l.Infof("Signal %d received; restarting", s) + cmd.Process.Signal(sigHup) + err = <-exit + case err = <-exit: if err == nil { // Successful exit indicates an intentional shutdown