From 538e35f61bc293bb2adf8b437afdeab4d27b6e53 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 11 Mar 2020 19:56:13 -0700 Subject: Fix race condition (*tcp.endpoint).Close Atomically close the endpoint. Before this change, it was possible for multiple callers to perform duplicate work. PiperOrigin-RevId: 300462110 --- pkg/tcpip/transport/tcp/endpoint.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index cf73f5382..5187a5e25 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -825,6 +825,7 @@ func (e *endpoint) Abort() { func (e *endpoint) Close() { e.mu.Lock() closed := e.closed + e.closed = true e.mu.Unlock() if closed { return @@ -833,13 +834,7 @@ func (e *endpoint) Close() { // Issue a shutdown so that the peer knows we won't send any more data // if we're connected, or stop accepting if we're listening. e.Shutdown(tcpip.ShutdownWrite | tcpip.ShutdownRead) - e.closeNoShutdown() -} -// closeNoShutdown closes the endpoint without doing a full shutdown. This is -// used when a connection needs to be aborted with a RST and we want to skip -// a full 4 way TCP shutdown. -func (e *endpoint) closeNoShutdown() { e.mu.Lock() // For listening sockets, we always release ports inline so that they @@ -858,8 +853,6 @@ func (e *endpoint) closeNoShutdown() { e.boundPortFlags = ports.Flags{} } - // Mark endpoint as closed. - e.closed = true // Either perform the local cleanup or kick the worker to make sure it // knows it needs to cleanup. switch e.EndpointState() { -- cgit v1.2.3