浏览代码

Fix leak of watchMiss goroutine

The netlink socket that was used to monitor the L2
miss was never being closed. The watchMiss goroutine
spawned was never returning. This was causing goroutine
leak in case of createNetwork/destroyNetwork

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
Flavio Crisciani 8 年之前
父节点
当前提交
d5c69190d1
共有 1 个文件被更改,包括 21 次插入0 次删除
  1. 21 0
      libnetwork/drivers/overlay/ov_network.go

+ 21 - 0
libnetwork/drivers/overlay/ov_network.go

@@ -58,6 +58,7 @@ type network struct {
 	dbIndex   uint64
 	dbExists  bool
 	sbox      osl.Sandbox
+	nlSocket  *nl.NetlinkSocket
 	endpoints endpointTable
 	driver    *driver
 	joinCnt   int
@@ -345,6 +346,12 @@ func (n *network) destroySandbox() {
 			}
 		}
 
+		// Close the netlink socket, this will also release the watchMiss goroutine that is using it
+		if n.nlSocket != nil {
+			n.nlSocket.Close()
+			n.nlSocket = nil
+		}
+
 		n.sbox.Destroy()
 		n.sbox = nil
 	}
@@ -685,6 +692,7 @@ func (n *network) initSandbox(restore bool) error {
 	sbox.InvokeFunc(func() {
 		nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH)
 	})
+	n.setNetlinkSocket(nlSock)
 
 	if err == nil {
 		go n.watchMiss(nlSock)
@@ -700,6 +708,13 @@ func (n *network) watchMiss(nlSock *nl.NetlinkSocket) {
 	for {
 		msgs, err := nlSock.Receive()
 		if err != nil {
+			n.Lock()
+			nlFd := nlSock.GetFd()
+			n.Unlock()
+			if nlFd == -1 {
+				// The netlink socket got closed, simply exit to not leak this goroutine
+				return
+			}
 			logrus.Errorf("Failed to receive from netlink: %v ", err)
 			continue
 		}
@@ -816,6 +831,12 @@ func (n *network) setSandbox(sbox osl.Sandbox) {
 	n.Unlock()
 }
 
+func (n *network) setNetlinkSocket(nlSk *nl.NetlinkSocket) {
+	n.Lock()
+	n.nlSocket = nlSk
+	n.Unlock()
+}
+
 func (n *network) vxlanID(s *subnet) uint32 {
 	n.Lock()
 	defer n.Unlock()