From 4b5711d4b43edd307411d71d32981696049b22b1 Mon Sep 17 00:00:00 2001 From: meermonster10 <56380202+meermonster10@users.noreply.github.com> Date: Thu, 10 Oct 2019 07:57:57 +0200 Subject: [PATCH 1/2] docker-proxy-close-dangling-sockets Make docker-proxy more resilient to CLOSE_WAIT and FIN_WAIT2 socket states. In case of unexpected connection terminations, do not wait indefinitely until both ends are closed. --- cmd/proxy/tcp_proxy.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cmd/proxy/tcp_proxy.go b/cmd/proxy/tcp_proxy.go index 4ac643a788..9d2b610fe6 100644 --- a/cmd/proxy/tcp_proxy.go +++ b/cmd/proxy/tcp_proxy.go @@ -4,7 +4,7 @@ import ( "io" "log" "net" - "sync" + "time" ) // TCPProxy is a proxy for TCP connections. It implements the Proxy interface to @@ -38,21 +38,36 @@ func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) { return } - var wg sync.WaitGroup + // Use this channel to follow the execution status + // of our goroutines :D + done := make(chan bool) + var broker = func(to, from *net.TCPConn) { io.Copy(to, from) from.CloseRead() to.CloseWrite() - wg.Done() + done <- true + } - wg.Add(2) go broker(client, backend) go broker(backend, client) finish := make(chan struct{}) go func() { - wg.Wait() + + //Wait until at least one function exits + <-done + + //After one end of the connection is closed wait for max 30 sec + //until the other end is closed as well + //This is to prevent that CLOSE_WAIT and SYN_WAIT2 socket states + //accumulate the open sockets by docker-proxy + select { + case <-done: + case <-time.After(30 * time.Second): + } + close(finish) }() From 7079e0cee82217f55b4fae5a9f448343e973d3b3 Mon Sep 17 00:00:00 2001 From: meermonster10 <56380202+meermonster10@users.noreply.github.com> Date: Thu, 10 Oct 2019 07:57:57 +0200 Subject: [PATCH 2/2] docker-proxy-close-dangling-sockets Make docker-proxy more resilient to CLOSE_WAIT and FIN_WAIT2 socket states. In case of unexpected connection terminations, do not wait indefinitely until both ends are closed. Signed-off-by: Jason Kim --- cmd/proxy/tcp_proxy.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cmd/proxy/tcp_proxy.go b/cmd/proxy/tcp_proxy.go index 4ac643a788..9d2b610fe6 100644 --- a/cmd/proxy/tcp_proxy.go +++ b/cmd/proxy/tcp_proxy.go @@ -4,7 +4,7 @@ import ( "io" "log" "net" - "sync" + "time" ) // TCPProxy is a proxy for TCP connections. It implements the Proxy interface to @@ -38,21 +38,36 @@ func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) { return } - var wg sync.WaitGroup + // Use this channel to follow the execution status + // of our goroutines :D + done := make(chan bool) + var broker = func(to, from *net.TCPConn) { io.Copy(to, from) from.CloseRead() to.CloseWrite() - wg.Done() + done <- true + } - wg.Add(2) go broker(client, backend) go broker(backend, client) finish := make(chan struct{}) go func() { - wg.Wait() + + //Wait until at least one function exits + <-done + + //After one end of the connection is closed wait for max 30 sec + //until the other end is closed as well + //This is to prevent that CLOSE_WAIT and SYN_WAIT2 socket states + //accumulate the open sockets by docker-proxy + select { + case <-done: + case <-time.After(30 * time.Second): + } + close(finish) }()