Переглянути джерело

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()