From 062f5e4794d3a16107270969fc506fee8480ee7d Mon Sep 17 00:00:00 2001 From: Collecting Date: Wed, 14 Jan 2026 19:35:54 +0000 Subject: [PATCH 1/3] bsd.h: Add Table Mutex Signed-off-by: Collecting --- src/core/hle/service/sockets/bsd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index d65ea820c..750e000d9 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -203,6 +203,7 @@ private: void BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept; std::array, MAX_FD> file_descriptors; + std::mutex fd_table_mutex; // Protects access to the file_descriptors array Network::RoomNetwork& room_network; From 5a7a9c9bb8ec7280066c9d858e8b6254a2cabee1 Mon Sep 17 00:00:00 2001 From: Collecting Date: Wed, 14 Jan 2026 19:36:36 +0000 Subject: [PATCH 2/3] bsd.cpp: Add Guards & Mutex for Socket Protection Signed-off-by: Collecting --- src/core/hle/service/sockets/bsd.cpp | 37 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 971b7b0a5..c9a77203b 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -1009,35 +1009,39 @@ Errno BSD::CloseImpl(s32 fd) { return Errno::BADF; } - auto& descriptor = file_descriptors[fd]; - const Errno bsd_errno = Translate(descriptor->socket->Close()); + // Capture the socket pointer and info before we lock and reset the table entry + std::shared_ptr socket_to_close; + SocketPoolKey key; + bool is_proxy = false; + + { + std::lock_guard lock(fd_table_mutex); + auto& descriptor = file_descriptors[fd]; + socket_to_close = descriptor->socket; + key = {descriptor->domain, descriptor->type, descriptor->protocol}; + is_proxy = std::dynamic_pointer_cast(socket_to_close) != nullptr; + + // Remove it from the table immediately so OnProxyPacketReceived stops seeing it + file_descriptors[fd].reset(); + } + + const Errno bsd_errno = Translate(socket_to_close->Close()); if (bsd_errno != Errno::SUCCESS) { return bsd_errno; } LOG_INFO(Service, "Close socket fd={}", fd); - // Try to return ProxySocket to the pool for reuse - auto proxy_socket = std::dynamic_pointer_cast(descriptor->socket); auto room_member = room_network.GetRoomMember().lock(); - - if (proxy_socket && room_member && room_member->IsConnected()) { - // Socket is still valid, add to pool + if (is_proxy && room_member && room_member->IsConnected()) { std::lock_guard lock(socket_pool_mutex); - - SocketPoolKey key{descriptor->domain, descriptor->type, descriptor->protocol}; - - // Limit pool size to avoid memory bloat (max 8 sockets per type) constexpr size_t MAX_POOL_SIZE = 8; if (socket_pool[key].size() < MAX_POOL_SIZE) { - socket_pool[key].push_back(descriptor->socket); + socket_pool[key].push_back(socket_to_close); LOG_DEBUG(Service, "Returned socket fd={} to pool", fd); - } else { - LOG_DEBUG(Service, "Socket pool full, destroying socket fd={}", fd); } } - file_descriptors[fd].reset(); return bsd_errno; } @@ -1093,6 +1097,9 @@ void BSD::BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noex } void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) { + // Lock the table so CloseImpl doesn't delete a socket while we are iterating + std::lock_guard lock(fd_table_mutex); + // We must ensure we only deliver the packet ONCE std::vector processed_sockets; From 4f149e130c6b8102fcd1464694b3a9a5e7200187 Mon Sep 17 00:00:00 2001 From: Collecting Date: Wed, 14 Jan 2026 19:37:29 +0000 Subject: [PATCH 3/3] socket_proxy.cpp: Add Mutex & Flush for Socket Protection Signed-off-by: Collecting --- src/core/internal_network/socket_proxy.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index 6f8288c9b..b6368e4b5 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -307,9 +307,15 @@ std::pair ProxySocket::SendTo(u32 flags, std::span message } Errno ProxySocket::Close() { + std::lock_guard guard(packets_mutex); fd = INVALID_SOCKET; closed = true; + // Flush any pending packets so they don't get processed after closure + while (!received_packets.empty()) { + received_packets.pop(); + } + return Errno::SUCCESS; }