Improve API/GUI shutdown handling (fixes #2694)

This fixes both a race condition where we could assign s.stop from one
goroutine and then read it from another without locking, and handles the
fact that listener may be nil at shutdown if we've had a bad
CommitConfiguration call in the meantime.
This commit is contained in:
Jakob Borg
2016-01-14 11:06:36 +01:00
parent 74a210f198
commit 97b1c66d4a
2 changed files with 91 additions and 10 deletions

View File

@@ -6,7 +6,13 @@
package main
import "testing"
import (
"testing"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/thejerf/suture"
)
func TestCSRFToken(t *testing.T) {
t1 := newCsrfToken()
@@ -40,3 +46,46 @@ func TestCSRFToken(t *testing.T) {
t.Fatal("t3 should have expired by now")
}
}
func TestStopAfterBrokenConfig(t *testing.T) {
baseDirs["config"] = "../../test/h1" // to load HTTPS keys
expandLocations()
cfg := config.Configuration{
GUI: config.GUIConfiguration{
RawAddress: "127.0.0.1:0",
RawUseTLS: false,
},
}
w := config.Wrap("/dev/null", cfg)
srv, err := newAPIService(protocol.LocalDeviceID, w, "", nil, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
srv.started = make(chan struct{})
sup := suture.NewSimple("test")
sup.Add(srv)
sup.ServeBackground()
<-srv.started
// Service is now running, listening on a random port on localhost. Now we
// request a config change to a completely invalid listen address. The
// commit will fail and the service will be in a broken state.
newCfg := config.Configuration{
GUI: config.GUIConfiguration{
RawAddress: "totally not a valid address",
RawUseTLS: false,
},
}
if srv.CommitConfiguration(cfg, newCfg) {
t.Fatal("Config commit should have failed")
}
// Nonetheless, it should be fine to Stop() it without panic.
sup.Stop()
}