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/StringUtil.h"
#include "common/ScopedGuard.h"
#ifdef _WIN32
#include <winsock2.h>
@ -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())
{

View File

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