Fix an invalid foreach loop over an unordered_map with deletion in WiiSockets

This commit is contained in:
galop1n
2014-06-27 12:26:11 -04:00
committed by lioncash
parent bd377b9580
commit 729758f2f9
2 changed files with 17 additions and 12 deletions

View File

@ -570,8 +570,9 @@ s32 WiiSockMan::NewSocket(s32 af, s32 type, s32 protocol)
s32 WiiSockMan::DeleteSocket(s32 s) s32 WiiSockMan::DeleteSocket(s32 s)
{ {
s32 ReturnValue = WiiSockets[s].CloseFd(); auto socket_entry = WiiSockets.find(s);
WiiSockets.erase(s); s32 ReturnValue = socket_entry->second.CloseFd();
WiiSockets.erase(socket_entry);
return ReturnValue; return ReturnValue;
} }
@ -583,20 +584,25 @@ void WiiSockMan::Update()
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_ZERO(&write_fds); FD_ZERO(&write_fds);
FD_ZERO(&except_fds); FD_ZERO(&except_fds);
for (auto& entry : WiiSockets)
auto socket_iter = WiiSockets.begin();
auto end_socks = WiiSockets.end();
while (socket_iter != end_socks)
{ {
WiiSocket& sock = entry.second; WiiSocket& sock = socket_iter->second;
if (sock.IsValid()) if (sock.IsValid())
{ {
FD_SET(sock.fd, &read_fds); FD_SET(sock.fd, &read_fds);
FD_SET(sock.fd, &write_fds); FD_SET(sock.fd, &write_fds);
FD_SET(sock.fd, &except_fds); FD_SET(sock.fd, &except_fds);
nfds = std::max(nfds, sock.fd+1); nfds = std::max(nfds, sock.fd+1);
++socket_iter;
} }
else else
{ {
// Good time to clean up invalid sockets. // Good time to clean up invalid sockets.
WiiSockets.erase(sock.fd); socket_iter = WiiSockets.erase(socket_iter);
} }
} }
s32 ret = select(nfds, &read_fds, &write_fds, &except_fds, &t); s32 ret = select(nfds, &read_fds, &write_fds, &except_fds, &t);

View File

@ -192,7 +192,7 @@ public:
}; };
class WiiSockMan class WiiSockMan : public ::NonCopyable
{ {
public: public:
static s32 GetNetErrorCode(s32 ret, std::string caller, bool isRW); static s32 GetNetErrorCode(s32 ret, std::string caller, bool isRW);
@ -222,7 +222,8 @@ public:
template <typename T> template <typename T>
void DoSock(s32 sock, u32 CommandAddress, T type) void DoSock(s32 sock, u32 CommandAddress, T type)
{ {
if (WiiSockets.find(sock) == WiiSockets.end()) auto socket_entry = WiiSockets.find(sock);
if (socket_entry == WiiSockets.end())
{ {
IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(CommandAddress)); IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(CommandAddress));
ERROR_LOG(WII_IPC_NET, ERROR_LOG(WII_IPC_NET,
@ -232,15 +233,13 @@ public:
} }
else else
{ {
WiiSockets[sock].DoSock(CommandAddress, type); socket_entry->second.DoSock(CommandAddress, type);
} }
} }
private: private:
WiiSockMan() {}; // Constructor? (the {} brackets) are needed here. WiiSockMan() = default;
WiiSockMan(WiiSockMan const&); // Don't Implement
void operator=(WiiSockMan const&); // Don't implement
std::unordered_map<s32, WiiSocket> WiiSockets;
std::unordered_map<s32, WiiSocket> WiiSockets;
s32 errno_last; s32 errno_last;
}; };