From d6b32aac3c75a6a0c4190a8b6b2b1fbc5f3e8801 Mon Sep 17 00:00:00 2001 From: cirakg Date: Tue, 3 Nov 2026 01:15:29 +0100 Subject: network: keep fcntl modes across MSG_DONTWAIT and decompress room packets once A receive with MSG_DONTWAIT restored the blocking mode from the descriptor copy taken before the call. When fcntl(SETFL, O_NONBLOCK) ran during the receive, the fd kept reporting O_NONBLOCK while its socket blocked again. Receives now switch the mode only for MSG_DONTWAIT and read the current flags under file_descriptors_mutex at both ends, and SETFL changes the mode and the stored flags in the same critical section. OnProxyPacketReceived decompressed each room packet once per matching socket while holding file_descriptors_mutex, so every bsd call waited for it. It now copies the distinct sockets under the lock, decompresses once without it and delivers the result. Also reject fd == MAX_FD in IsFileDescriptorValid and PollImpl, which read past the table, and guard the ProxySocket blocking and receive timeout setters with packets_mutex, matching their reader. Assisted-by: Claude Opus 5.5 (investigation and implementation) --- src/core/internal_network/socket_proxy.cpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'src/core/internal_network/socket_proxy.cpp') diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index 1b93ce93e5..95f64b9bd0 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -43,22 +43,7 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) { LOG_INFO(Network, "Received broadcast packet, but not configured for broadcast mode"); return; } - } - - // Decompress without the lock, so the game thread does not wait for it - ProxyPacket decompressed{ - .local_endpoint = packet.local_endpoint, - .remote_endpoint = packet.remote_endpoint, - .protocol = packet.protocol, - .broadcast = packet.broadcast, - .data = Common::Compression::DecompressDataZSTD(packet.data), - }; - { - std::lock_guard guard(packets_mutex); - if (closed) { - return; - } - received_packets.push(std::move(decompressed)); + received_packets.push(packet); } // A MSG_PEEK reader leaves the packet queued, so every waiter must see it packets_cv.notify_all(); @@ -304,11 +289,15 @@ Errno ProxySocket::SetSndTimeo(u32 value) { } Errno ProxySocket::SetRcvTimeo(u32 value) { - receive_timeout = value; + { + std::lock_guard guard(packets_mutex); + receive_timeout = value; + } return SetSockOpt(fd, SO_RCVTIMEO, static_cast(value)); } Errno ProxySocket::SetNonBlock(bool enable) { + std::lock_guard guard(packets_mutex); blocking = !enable; return Errno::SUCCESS; } -- cgit v1.2.3