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