From 2bf14200f7c678cd957309b910f21ae277bf9337 Mon Sep 17 00:00:00 2001 From: dongresource Date: Sat, 11 Mar 2023 02:59:05 +0100 Subject: [PATCH] Make CNSocket::kill() idempotent CNSocket::kill() will now no longer call close() on already closed sockets. close() should never be called on already closed file descriptors, yet CNSocket::kill() was lacking any protection against that, despite its use as both a high-level way of killing player connections and as a means of ensuring that closing connections have been properly terminated in the poll() loop. This was causing close() to be erroneously called on each socket at least one extra time. It was also introducing a race condition where the login and shard threads could close each other's newly opened sockets due to file descriptor reuse when a connection was accept()ed after the first call to close(), but before the second one. See the close(2) manpage for details. --- src/core/CNProtocol.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/CNProtocol.cpp b/src/core/CNProtocol.cpp index 9ebf98d..a54f35e 100644 --- a/src/core/CNProtocol.cpp +++ b/src/core/CNProtocol.cpp @@ -109,7 +109,11 @@ bool CNSocket::isAlive() { } void CNSocket::kill() { + if (!alive) + return; + alive = false; + #ifdef _WIN32 shutdown(sock, SD_BOTH); closesocket(sock);