浏览代码

lib/protocol: Return from ClusterConfig when closed (#5752)

Simon Frei 6 年之前
父节点
当前提交
6664e01acf
共有 2 个文件被更改,包括 28 次插入2 次删除
  1. 5 2
      lib/protocol/protocol.go
  2. 23 0
      lib/protocol/protocol_test.go

+ 5 - 2
lib/protocol/protocol.go

@@ -332,8 +332,11 @@ func (c *rawConnection) Request(folder string, name string, offset int64, size i
 // ClusterConfig sends the cluster configuration message to the peer.
 // ClusterConfig sends the cluster configuration message to the peer.
 // It must be called just once (as per BEP), otherwise it will panic.
 // It must be called just once (as per BEP), otherwise it will panic.
 func (c *rawConnection) ClusterConfig(config ClusterConfig) {
 func (c *rawConnection) ClusterConfig(config ClusterConfig) {
-	c.clusterConfigBox <- &config
-	close(c.clusterConfigBox)
+	select {
+	case c.clusterConfigBox <- &config:
+		close(c.clusterConfigBox)
+	case <-c.closed:
+	}
 }
 }
 
 
 func (c *rawConnection) Closed() bool {
 func (c *rawConnection) Closed() bool {

+ 23 - 0
lib/protocol/protocol_test.go

@@ -757,3 +757,26 @@ func TestSha256OfEmptyBlock(t *testing.T) {
 		}
 		}
 	}
 	}
 }
 }
+
+// TestClusterConfigAfterClose checks that ClusterConfig does not deadlock when
+// ClusterConfig is called on a closed connection.
+func TestClusterConfigAfterClose(t *testing.T) {
+	m := newTestModel()
+
+	c := NewConnection(c0ID, &testutils.BlockingRW{}, &testutils.BlockingRW{}, m, "name", CompressAlways).(wireFormatConnection).Connection.(*rawConnection)
+	c.Start()
+
+	c.internalClose(errManual)
+
+	done := make(chan struct{})
+	go func() {
+		c.ClusterConfig(ClusterConfig{})
+		close(done)
+	}()
+
+	select {
+	case <-done:
+	case <-time.After(time.Second):
+		t.Fatal("timed out before Cluster Config returned")
+	}
+}