diff options
author | Mithun Iyer <iyerm@google.com> | 2020-11-09 14:52:50 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-11-09 14:54:57 -0800 |
commit | 199fcd0fe512f2fa4af63b0ec74e36aea7c4a8e1 (patch) | |
tree | df4a8866f0d479451039ce06adf78cbce9d04f06 /pkg/tcpip/transport/tcp | |
parent | 2fcca60a7bf084a28e878941d9dcb47e11268cbd (diff) |
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
Diffstat (limited to 'pkg/tcpip/transport/tcp')
-rw-r--r-- | pkg/tcpip/transport/tcp/connect.go | 1 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/endpoint.go | 11 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/tcp_test.go | 4 |
3 files changed, 9 insertions, 7 deletions
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} |