Bläddra i källkod

Proper signal handling in monitor process

Jakob Borg 11 år sedan
förälder
incheckning
33e9a88b56
4 ändrade filer med 39 tillägg och 12 borttagningar
  1. 22 3
      cmd/syncthing/monitor.go
  2. 1 1
      integration/all.sh
  3. 6 1
      integration/common_test.go
  4. 10 7
      integration/reconnect_test.go

+ 22 - 3
cmd/syncthing/monitor.go

@@ -9,9 +9,11 @@ import (
 	"io"
 	"os"
 	"os/exec"
+	"os/signal"
 	"path/filepath"
 	"strings"
 	"sync"
+	"syscall"
 	"time"
 )
 
@@ -33,6 +35,10 @@ 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)
+
 	for {
 		if t := time.Since(restarts[0]); t < loopThreshold {
 			l.Warnf("%d restarts in %v; not retrying further", countRestarts, t)
@@ -68,10 +74,23 @@ func monitorMain() {
 		go copyStderr(stderr)
 		go copyStdout(stdout)
 
-		err = cmd.Wait()
-		if err == nil {
-			// Successfull exit indicates an intentional shutdown
+		exit := make(chan error)
+
+		go func() {
+			exit <- cmd.Wait()
+		}()
+
+		select {
+		case s := <-sign:
+			l.Infof("Signal %d received; exiting", s)
+			cmd.Process.Kill()
+			<-exit
 			return
+		case <-exit:
+			if err == nil {
+				// Successfull exit indicates an intentional shutdown
+				return
+			}
 		}
 
 		l.Infoln("Syncthing exited:", err)

+ 1 - 1
integration/all.sh

@@ -2,7 +2,7 @@
 set -euo pipefail
 IFS=$'\n\t'
 
-#go test -tags integration -v
 ./test-http.sh
 ./test-merge.sh
 ./test-delupd.sh
+go test -tags integration -v

+ 6 - 1
integration/common_test.go

@@ -19,6 +19,7 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"runtime"
 	"time"
 )
 
@@ -54,7 +55,11 @@ func (p *syncthingProcess) start() error {
 }
 
 func (p *syncthingProcess) stop() {
-	p.cmd.Process.Kill()
+	if runtime.GOOS != "windows" {
+		p.cmd.Process.Signal(os.Interrupt)
+	} else {
+		p.cmd.Process.Kill()
+	}
 	p.cmd.Wait()
 }
 

+ 10 - 7
integration/reconnect_test.go

@@ -24,13 +24,6 @@ var env = []string{
 	"STTRACE=model",
 }
 
-func TestRestartBothDuringTransfer(t *testing.T) {
-	// Give the receiver some time to rot with needed files but
-	// without any peer. This triggers
-	// https://github.com/syncthing/syncthing/issues/463
-	testRestartDuringTransfer(t, true, true, 10*time.Second, 0)
-}
-
 func TestRestartReceiverDuringTransfer(t *testing.T) {
 	testRestartDuringTransfer(t, false, true, 0, 0)
 }
@@ -39,6 +32,13 @@ func TestRestartSenderDuringTransfer(t *testing.T) {
 	testRestartDuringTransfer(t, true, false, 0, 0)
 }
 
+func TestRestartSenderAndReceiverDuringTransfer(t *testing.T) {
+	// 	// Give the receiver some time to rot with needed files but
+	// 	// without any peer. This triggers
+	// 	// https://github.com/syncthing/syncthing/issues/463
+	testRestartDuringTransfer(t, true, true, 10*time.Second, 0)
+}
+
 func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool, senderDelay, receiverDelay time.Duration) {
 	log.Println("Cleaning...")
 	err := removeAll("s1", "s2", "f1/index", "f2/index")
@@ -134,6 +134,9 @@ func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool
 		time.Sleep(1 * time.Second)
 	}
 
+	sender.stop()
+	receiver.stop()
+
 	log.Println("Comparing directories...")
 	err = compareDirectories("s1", "s2")
 	if err != nil {