From 199fcd0fe512f2fa4af63b0ec74e36aea7c4a8e1 Mon Sep 17 00:00:00 2001 From: Mithun Iyer Date: Mon, 9 Nov 2020 14:52:50 -0800 Subject: Skip `EventHUp` notify in `FIN_WAIT2` on a socket close. This Notify was added as part of cl/279106406; but notifying `EventHUp` in `FIN_WAIT2` is incorrect, as we want to only notify later on `TIME_WAIT` or a reset. However, we do need to notify any blocked waiters of an activity on the endpoint with `EventIn`|`EventOut`. PiperOrigin-RevId: 341490913 --- pkg/tcpip/transport/tcp/connect.go | 1 - pkg/tcpip/transport/tcp/endpoint.go | 11 +++++++---- pkg/tcpip/transport/tcp/tcp_test.go | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'pkg/tcpip/transport') diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index 2facbebec..6e9015be1 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -1451,7 +1451,6 @@ func (e *endpoint) protocolMainLoop(handshake bool, wakerInitDone chan<- struct{ // The socket has been closed and we are in FIN_WAIT2 // so start the FIN_WAIT2 timer. closeTimer = time.AfterFunc(e.tcpLingerTimeout, closeWaker.Assert) - e.waiterQueue.Notify(waiter.EventHUp | waiter.EventErr | waiter.EventIn | waiter.EventOut) } } diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 258f9f1bb..23b9de8c5 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -1069,9 +1069,7 @@ func (e *endpoint) Close() { e.closeNoShutdownLocked() } -// 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. +// closeNoShutdown closes the endpoint without doing a full shutdown. func (e *endpoint) closeNoShutdownLocked() { // For listening sockets, we always release ports inline so that they // are immediately available for reuse after Close() is called. If also @@ -1098,6 +1096,7 @@ func (e *endpoint) closeNoShutdownLocked() { return } + eventMask := waiter.EventIn | waiter.EventOut // Either perform the local cleanup or kick the worker to make sure it // knows it needs to cleanup. if e.workerRunning { @@ -1109,8 +1108,12 @@ func (e *endpoint) closeNoShutdownLocked() { } else { e.transitionToStateCloseLocked() // Notify that the endpoint is closed. - e.waiterQueue.Notify(waiter.EventHUp) + eventMask |= waiter.EventHUp } + + // The TCP closing state-machine would eventually notify EventHUp, but we + // notify EventIn|EventOut immediately to unblock any blocked waiters. + e.waiterQueue.Notify(eventMask) } // closePendingAcceptableConnections closes all connections that have completed diff --git a/pkg/tcpip/transport/tcp/tcp_test.go b/pkg/tcpip/transport/tcp/tcp_test.go index 5f05608e2..fcc3c5000 100644 --- a/pkg/tcpip/transport/tcp/tcp_test.go +++ b/pkg/tcpip/transport/tcp/tcp_test.go @@ -63,7 +63,7 @@ func TestGiveUpConnect(t *testing.T) { // Register for notification, then start connection attempt. waitEntry, notifyCh := waiter.NewChannelEntry(nil) - wq.EventRegister(&waitEntry, waiter.EventOut) + wq.EventRegister(&waitEntry, waiter.EventHUp) defer wq.EventUnregister(&waitEntry) if err := ep.Connect(tcpip.FullAddress{Addr: context.TestAddr, Port: context.TestPort}); err != tcpip.ErrConnectStarted { @@ -1448,7 +1448,7 @@ func TestSynSent(t *testing.T) { // Start connection attempt. waitEntry, ch := waiter.NewChannelEntry(nil) - c.WQ.EventRegister(&waitEntry, waiter.EventOut) + c.WQ.EventRegister(&waitEntry, waiter.EventHUp) defer c.WQ.EventUnregister(&waitEntry) addr := tcpip.FullAddress{Addr: context.TestAddr, Port: context.TestPort} -- cgit v1.2.3