From 21d8366023e8f06b41e93324cbf038516eb56b9c Mon Sep 17 00:00:00 2001 From: Thad House Date: Mon, 9 Sep 2024 21:25:54 -0700 Subject: [PATCH] Set SO_REUSEADDR on epoll tcp listener sockets 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));