From 6976ecff74d7896d6b1c7e7b8ec9cb6b7d7ce72d Mon Sep 17 00:00:00 2001 From: Thad House Date: Wed, 11 Sep 2024 14:25:33 -0700 Subject: [PATCH] Set SO_REUSEADDR on epoll tcp listener sockets (#4544) Unix is a bit more strict about TIME_WAIT state, and actually puts any sockets that have had a valid accept() called on them into the TIME_WAIT state. This makes writing a listener app difficult, as if that ever crashes the bind() will fail for the next few minutes. Pretty much all other TCP libraries set SO_REUSEADDR (Including libuv, which is what our app has used before). Libuv sets it on all TCP sockets, but its generally less required on client sockets, as they rarely actually specify a local port. --- src/platform/datapath_epoll.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/platform/datapath_epoll.c b/src/platform/datapath_epoll.c index 4774c077de..1c2e260b49 100644 --- a/src/platform/datapath_epoll.c +++ b/src/platform/datapath_epoll.c @@ -926,6 +926,29 @@ CxPlatSocketContextInitialize( goto Exit; } } + } else if (SocketType == CXPLAT_SOCKET_TCP_LISTENER) { + // + // Set SO_REUSEADDR on listener sockets to avoid + // TIME_WAIT state on shutdown. + // + Option = TRUE; + Result = + setsockopt( + SocketContext->SocketFd, + SOL_SOCKET, + SO_REUSEADDR, + (const void*)&Option, + sizeof(Option)); + if (Result == SOCKET_ERROR) { + Status = errno; + QuicTraceEvent( + DatapathErrorStatus, + "[data][%p] ERROR, %u, %s.", + Binding, + Status, + "setsockopt(SO_REUSEPORT) failed"); + goto Exit; + } } CxPlatCopyMemory(&MappedAddress, &Binding->LocalAddress, sizeof(MappedAddress));