mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 11:58:28 +00:00
parent
6b1d7ac727
commit
02752af862
@ -14,6 +14,7 @@ type TestModel struct {
|
|||||||
weakHash uint32
|
weakHash uint32
|
||||||
fromTemporary bool
|
fromTemporary bool
|
||||||
indexFn func(DeviceID, string, []FileInfo)
|
indexFn func(DeviceID, string, []FileInfo)
|
||||||
|
ccFn func(DeviceID, ClusterConfig)
|
||||||
closedCh chan struct{}
|
closedCh chan struct{}
|
||||||
closedErr error
|
closedErr error
|
||||||
}
|
}
|
||||||
@ -52,6 +53,9 @@ func (t *TestModel) Closed(conn Connection, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestModel) ClusterConfig(deviceID DeviceID, config ClusterConfig) {
|
func (t *TestModel) ClusterConfig(deviceID DeviceID, config ClusterConfig) {
|
||||||
|
if t.ccFn != nil {
|
||||||
|
t.ccFn(deviceID, config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestModel) DownloadProgress(DeviceID, string, []FileDownloadProgressUpdate) {
|
func (t *TestModel) DownloadProgress(DeviceID, string, []FileDownloadProgressUpdate) {
|
||||||
|
@ -882,7 +882,11 @@ func (c *rawConnection) Close(err error) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
c.internalClose(err)
|
// Close might be called from a method that is called from within
|
||||||
|
// dispatcherLoop, resulting in a deadlock.
|
||||||
|
// The sending above must happen before spawning the routine, to prevent
|
||||||
|
// the underlying connection from terminating before sending the close msg.
|
||||||
|
go c.internalClose(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// internalClose is called if there is an unexpected error during normal operation.
|
// internalClose is called if there is an unexpected error during normal operation.
|
||||||
|
@ -813,3 +813,22 @@ func TestClusterConfigAfterClose(t *testing.T) {
|
|||||||
t.Fatal("timed out before Cluster Config returned")
|
t.Fatal("timed out before Cluster Config returned")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDispatcherToCloseDeadlock(t *testing.T) {
|
||||||
|
// Verify that we don't deadlock when calling Close() from within one of
|
||||||
|
// the model callbacks (ClusterConfig).
|
||||||
|
m := newTestModel()
|
||||||
|
c := NewConnection(c0ID, &testutils.BlockingRW{}, &testutils.NoopRW{}, m, "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
|
||||||
|
m.ccFn = func(devID DeviceID, cc ClusterConfig) {
|
||||||
|
c.Close(errManual)
|
||||||
|
}
|
||||||
|
c.Start()
|
||||||
|
|
||||||
|
c.inbox <- &ClusterConfig{}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-c.dispatcherLoopStopped:
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
t.Fatal("timed out before dispatcher loop terminated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user