DEV9: Cancel read of TAP device on suspend/shutdown

CancelIo() must be performed on the thread that started the IO operation, hence the use of an event.
This commit is contained in:
TheLastRar 2020-12-18 20:53:21 +00:00 committed by refractionpcsx2
parent f19985c410
commit 54651731f9
4 changed files with 26 additions and 3 deletions

View File

@ -271,6 +271,9 @@ TAPAdapter::TAPAdapter()
write.Offset = 0; write.Offset = 0;
write.OffsetHigh = 0; write.OffsetHigh = 0;
write.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); write.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
cancel = CreateEvent(NULL, TRUE, FALSE, NULL);
isActive = true; isActive = true;
} }
@ -298,9 +301,20 @@ bool TAPAdapter::recv(NetPacket* pkt)
DWORD dwError = GetLastError(); DWORD dwError = GetLastError();
if (dwError == ERROR_IO_PENDING) if (dwError == ERROR_IO_PENDING)
{ {
WaitForSingleObject(read.hEvent, INFINITE); HANDLE readHandles[]{read.hEvent, cancel};
result = GetOverlappedResult(htap, &read, const DWORD waitResult = WaitForMultipleObjects(2, readHandles, FALSE, INFINITE);
&read_size, FALSE);
if (waitResult == WAIT_OBJECT_0 + 1)
{
CancelIo(htap);
//Wait for the I/O subsystem to acknowledge our cancellation
result = GetOverlappedResult(htap, &read,
&read_size, TRUE);
}
else
result = GetOverlappedResult(htap, &read,
&read_size, FALSE);
if (!result) if (!result)
{ {
} }
@ -367,12 +381,17 @@ bool TAPAdapter::send(NetPacket* pkt)
else else
return false; return false;
} }
void TAPAdapter::close()
{
SetEvent(cancel);
}
TAPAdapter::~TAPAdapter() TAPAdapter::~TAPAdapter()
{ {
if (!isActive) if (!isActive)
return; return;
CloseHandle(read.hEvent); CloseHandle(read.hEvent);
CloseHandle(write.hEvent); CloseHandle(write.hEvent);
CloseHandle(cancel);
TAPSetStatus(htap, FALSE); TAPSetStatus(htap, FALSE);
CloseHandle(htap); CloseHandle(htap);
isActive = false; isActive = false;

View File

@ -29,6 +29,7 @@ class TAPAdapter : public NetAdapter
{ {
HANDLE htap; HANDLE htap;
OVERLAPPED read, write; OVERLAPPED read, write;
HANDLE cancel;
bool isActive = false; bool isActive = false;
public: public:
@ -39,5 +40,6 @@ public:
virtual bool recv(NetPacket* pkt); virtual bool recv(NetPacket* pkt);
//sends the packet and deletes it when done (if successful).rv :true success //sends the packet and deletes it when done (if successful).rv :true success
virtual bool send(NetPacket* pkt); virtual bool send(NetPacket* pkt);
virtual void close();
virtual ~TAPAdapter(); virtual ~TAPAdapter();
}; };

View File

@ -73,6 +73,7 @@ void TermNet()
if (RxRunning) if (RxRunning)
{ {
RxRunning = false; RxRunning = false;
nif->close();
emu_printf("Waiting for RX-net thread to terminate.."); emu_printf("Waiting for RX-net thread to terminate..");
rx_thread.join(); rx_thread.join();
emu_printf(".done\n"); emu_printf(".done\n");

View File

@ -41,6 +41,7 @@ public:
virtual bool isInitialised() = 0; virtual bool isInitialised() = 0;
virtual bool recv(NetPacket* pkt) = 0; //gets a packet virtual bool recv(NetPacket* pkt) = 0; //gets a packet
virtual bool send(NetPacket* pkt) = 0; //sends the packet and deletes it when done virtual bool send(NetPacket* pkt) = 0; //sends the packet and deletes it when done
virtual void close() {}
virtual ~NetAdapter() {} virtual ~NetAdapter() {}
}; };