DEV9: Defer deletion of socket sessions

This commit is contained in:
TheLastRar 2024-04-29 22:38:33 +01:00 committed by Connor McLaughlin
parent ce734f8a0d
commit 8bfcbdebf3
2 changed files with 44 additions and 6 deletions

View File

@ -3,6 +3,7 @@
#include "common/Assertions.h" #include "common/Assertions.h"
#include "common/StringUtil.h" #include "common/StringUtil.h"
#include "common/ScopedGuard.h"
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
@ -216,6 +217,8 @@ SocketAdapter::SocketAdapter()
wsa_init = true; wsa_init = true;
#endif #endif
sendThreadId = std::this_thread::get_id();
initialized = true; initialized = true;
} }
@ -234,6 +237,13 @@ bool SocketAdapter::recv(NetPacket* pkt)
if (NetAdapter::recv(pkt)) if (NetAdapter::recv(pkt))
return true; return true;
ScopedGuard cleanup([&]() {
// Garbage collect closed connections
for (BaseSession* s : deleteQueueRecvThread)
delete s;
deleteQueueRecvThread.clear();
});
EthernetFrame* bFrame; EthernetFrame* bFrame;
if (!vRecBuffer.Dequeue(&bFrame)) if (!vRecBuffer.Dequeue(&bFrame))
{ {
@ -282,6 +292,14 @@ bool SocketAdapter::send(NetPacket* pkt)
if (NetAdapter::send(pkt)) if (NetAdapter::send(pkt))
return true; 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); EthernetFrame frame(pkt);
switch (frame.protocol) switch (frame.protocol)
@ -548,9 +566,12 @@ void SocketAdapter::HandleConnectionClosed(BaseSession* sender)
{ {
const ConnectionKey key = sender->key; const ConnectionKey key = sender->key;
connections.Remove(key); connections.Remove(key);
//Note, we delete something that is calling us
//this is probably going to cause issues // Defer deleting the connection untill we have left the calling session's callstack
delete sender; if (std::this_thread::get_id() == sendThreadId)
deleteQueueSendThread.push_back(sender);
else
deleteQueueRecvThread.push_back(sender);
switch (key.protocol) switch (key.protocol)
{ {
@ -577,9 +598,12 @@ void SocketAdapter::HandleFixedPortClosed(BaseSession* sender)
ConnectionKey key = sender->key; ConnectionKey key = sender->key;
connections.Remove(key); connections.Remove(key);
fixedUDPPorts.Remove(key.ps2Port); fixedUDPPorts.Remove(key.ps2Port);
//Note, we delete something that is calling us
//this is probably going to cause issues // Defer deleting the connection untill we have left the calling session's callstack
delete sender; 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); Console.WriteLn("DEV9: Socket: Closed Dead UDP Fixed Port to %d", key.ps2Port);
} }
@ -604,6 +628,16 @@ SocketAdapter::~SocketAdapter()
connections.Clear(); connections.Clear();
fixedUDPPorts.Clear(); //fixedUDP sessions already deleted via connections 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 //Clear out vRecBuffer
while (!vRecBuffer.IsQueueEmpty()) while (!vRecBuffer.IsQueueEmpty())
{ {

View File

@ -28,6 +28,10 @@ class SocketAdapter : public NetAdapter
ThreadSafeMap<Sessions::ConnectionKey, Sessions::BaseSession*> connections; ThreadSafeMap<Sessions::ConnectionKey, Sessions::BaseSession*> connections;
ThreadSafeMap<u16, Sessions::BaseSession*> fixedUDPPorts; ThreadSafeMap<u16, Sessions::BaseSession*> fixedUDPPorts;
std::thread::id sendThreadId;
std::vector<Sessions::BaseSession*> deleteQueueSendThread;
std::vector<Sessions::BaseSession*> deleteQueueRecvThread;
public: public:
SocketAdapter(); SocketAdapter();
virtual bool blocks(); virtual bool blocks();