-
Notifications
You must be signed in to change notification settings - Fork 560
Open
Labels
Description
Recently both our app and docker engine found fd count increase in a short time, after looking into the go-dockerclient source code and test, we find the AddEventListener and RemoveEventListener cause the problem: RemoveEventListener will not close connection, but after remove all listener and call AddEventListener again, the client will create a new connection.
After looking into the code, we find that the eventHijack
create the gorountine and will not return when we call RemoveEventListener :
https://github.com/fsouza/go-dockerclient/blob/main/event.go#L383
Now the newest go-dockerclient version has this problem.
The test:
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"time"
docker "github.com/fsouza/go-dockerclient"
)
func main() {
fmt.Println("Start running daemon")
//Init Docker client
endpoint := "unix:///var/run/docker.sock"
if len(os.Args) < 3 {
fmt.Printf(`Usage %s [unix-socket-path] [fd-path]
example: %s unix:///var/run/docker.sock /proc/$(pidof docker)/fd`, os.Args[0], os.Args[0])
os.Exit(2)
}
endpoint = os.Args[1]
fdDir := os.Args[2]
client, err := docker.NewClient(endpoint)
if err != nil {
log.Fatal(err)
}
for {
connect(client, endpoint, fdDir)
}
}
func connect(client *docker.Client, endpoint, fdDir string) {
arr, err := ioutil.ReadDir(fdDir)
if err != nil {
log.Fatalf("read fd dir error %s: %v", fdDir, err)
}
fmt.Println(time.Now().Format("Mon Jan 02 15:04:05"), "before connect fd count:", len(arr))
events := make(chan *docker.APIEvents)
client.AddEventListener(events)
defer func() {
client.RemoveEventListener(events)
}()
timeout := time.After(3 * time.Second)
select {
case msg := <-events:
if msg.Status == "start" {
fmt.Println("EVENT:" + msg.Status)
}
case <-timeout:
break
}
}