From 8bfcbdebf3bdab1022fc02feb339f51537540639 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Mon, 29 Apr 2024 22:38:33 +0100 Subject: [PATCH] DEV9: Defer deletion of socket sessions --- pcsx2/DEV9/sockets.cpp | 46 ++++++++++++++++++++++++++++++++++++------ pcsx2/DEV9/sockets.h | 4 ++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/pcsx2/DEV9/sockets.cpp b/pcsx2/DEV9/sockets.cpp index 9dc65a574af39..4c1aae975db33 100644 --- a/pcsx2/DEV9/sockets.cpp +++ b/pcsx2/DEV9/sockets.cpp @@ -3,6 +3,7 @@ #include "common/Assertions.h" #include "common/StringUtil.h" +#include "common/ScopedGuard.h" #ifdef _WIN32 #include @@ -216,6 +217,8 @@ SocketAdapter::SocketAdapter() wsa_init = true; #endif + sendThreadId = std::this_thread::get_id(); + initialized = true; } @@ -234,6 +237,13 @@ bool SocketAdapter::recv(NetPacket* pkt) if (NetAdapter::recv(pkt)) return true; + ScopedGuard cleanup([&]() { + // Garbage collect closed connections + for (BaseSession* s : deleteQueueRecvThread) + delete s; + deleteQueueRecvThread.clear(); + }); + EthernetFrame* bFrame; if (!vRecBuffer.Dequeue(&bFrame)) { @@ -282,6 +292,14 @@ bool SocketAdapter::send(NetPacket* pkt) if (NetAdapter::send(pkt)) return true; + pxAssert(std::this_thread::get_id() == sendThreadId); + ScopedGuard cleanup([&]() { + // Garbage collect closed connections + for (BaseSession* s : deleteQueueSendThread) + delete s; + deleteQueueSendThread.clear(); + }); + EthernetFrame frame(pkt); switch (frame.protocol) @@ -548,9 +566,12 @@ void SocketAdapter::HandleConnectionClosed(BaseSession* sender) { const ConnectionKey key = sender->key; connections.Remove(key); - //Note, we delete something that is calling us - //this is probably going to cause issues - delete sender; + + // Defer deleting the connection untill we have left the calling session's callstack + if (std::this_thread::get_id() == sendThreadId) + deleteQueueSendThread.push_back(sender); + else + deleteQueueRecvThread.push_back(sender); switch (key.protocol) { @@ -577,9 +598,12 @@ void SocketAdapter::HandleFixedPortClosed(BaseSession* sender) ConnectionKey key = sender->key; connections.Remove(key); fixedUDPPorts.Remove(key.ps2Port); - //Note, we delete something that is calling us - //this is probably going to cause issues - delete sender; + + // Defer deleting the connection untill we have left the calling session's callstack + if (std::this_thread::get_id() == sendThreadId) + deleteQueueSendThread.push_back(sender); + else + deleteQueueRecvThread.push_back(sender); Console.WriteLn("DEV9: Socket: Closed Dead UDP Fixed Port to %d", key.ps2Port); } @@ -604,6 +628,16 @@ SocketAdapter::~SocketAdapter() connections.Clear(); fixedUDPPorts.Clear(); //fixedUDP sessions already deleted via connections + //Clear out any delete queues + DevCon.WriteLn("DEV9: Socket: Found %d Connections in send delete queue", deleteQueueSendThread.size()); + DevCon.WriteLn("DEV9: Socket: Found %d Connections in recv delete queue", deleteQueueRecvThread.size()); + for (BaseSession* s : deleteQueueSendThread) + delete s; + for (BaseSession* s : deleteQueueRecvThread) + delete s; + deleteQueueSendThread.clear(); + deleteQueueRecvThread.clear(); + //Clear out vRecBuffer while (!vRecBuffer.IsQueueEmpty()) { diff --git a/pcsx2/DEV9/sockets.h b/pcsx2/DEV9/sockets.h index ca062c4eb8252..b6acf451f87bd 100644 --- a/pcsx2/DEV9/sockets.h +++ b/pcsx2/DEV9/sockets.h @@ -28,6 +28,10 @@ class SocketAdapter : public NetAdapter ThreadSafeMap connections; ThreadSafeMap fixedUDPPorts; + std::thread::id sendThreadId; + std::vector deleteQueueSendThread; + std::vector deleteQueueRecvThread; + public: SocketAdapter(); virtual bool blocks();