From ddb1818dd54d82e19e7f629e6a729bccb68bfcf1 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 12 Jan 2015 15:45:30 +0100 Subject: cNetwork: Added multithreading protection. --- src/OSSupport/CriticalSection.cpp | 1 + src/OSSupport/Network.cpp | 30 +++++++++++++++++++++++++++--- tests/Network/CMakeLists.txt | 8 +++++++- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/OSSupport/CriticalSection.cpp b/src/OSSupport/CriticalSection.cpp index 13a3e4d9f..5248356c5 100644 --- a/src/OSSupport/CriticalSection.cpp +++ b/src/OSSupport/CriticalSection.cpp @@ -1,5 +1,6 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules +#include "CriticalSection.h" diff --git a/src/OSSupport/Network.cpp b/src/OSSupport/Network.cpp index 2ef6ace3c..bee5bc09f 100644 --- a/src/OSSupport/Network.cpp +++ b/src/OSSupport/Network.cpp @@ -12,6 +12,7 @@ #include #include #include "Event.h" +#include "CriticalSection.h" @@ -197,6 +198,9 @@ protected: /** Container for all currently active connections on this server. */ cTCPLinkImplPtrs m_Connections; + /** Mutex protecting m_Connections againt multithreaded access. */ + cCriticalSection m_CS; + /** The callback called by LibEvent upon incoming connection. */ static void Callback(evconnlistener * a_Listener, evutil_socket_t a_Socket, sockaddr * a_Addr, int a_Len, void * a_Self); @@ -289,6 +293,9 @@ protected: /** Container for all pending IP lookups. */ cIPLookupPtrs m_IPLookups; + /** Mutex protecting all containers against multithreaded access. */ + cCriticalSection m_CS; + /** Initializes the LibEvent internals. */ cNetworkSingleton(void); @@ -587,6 +594,7 @@ void cTCPLinkImpl::Shutdown(void) void cTCPLinkImpl::Close(void) { + // Disable all events on the socket, but keep it alive (multithreading): bufferevent_disable(m_BufferEvent, EV_READ | EV_WRITE); if (m_Server == nullptr) { @@ -790,7 +798,10 @@ void cServerHandleImpl::Close(void) // Shutdown all connections: cTCPLinkImplPtrs Conns; - std::swap(Conns, m_Connections); + { + cCSLock Lock(m_CS); + std::swap(Conns, m_Connections); + } for (auto conn: Conns) { conn->Shutdown(); @@ -902,7 +913,10 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_ // Create a new cTCPLink for the incoming connection: cTCPLinkImplPtr Link = std::make_shared(a_Socket, Self->m_LinkCallbacks, Self, a_Addr, a_Len); - Self->m_Connections.push_back(Link); + { + cCSLock Lock(Self->m_CS); + Self->m_Connections.push_back(Link); + } // Lock(m_CS) // Call the OnAccepted callback: Self->m_ListenCallbacks->OnAccepted(*Link); @@ -914,6 +928,7 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_ void cServerHandleImpl::RemoveLink(const cTCPLinkImpl * a_Link) { + cCSLock Lock(m_CS); for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) { if (itr->get() == a_Link) @@ -1060,7 +1075,10 @@ bool cNetworkSingleton::Connect( { // Add a connection request to the queue: cTCPLinkImplPtr ConnRequest = std::make_shared(a_LinkCallbacks); - m_Connections.push_back(ConnRequest); + { + cCSLock Lock(m_CS); + m_Connections.push_back(ConnRequest); + } // Lock(m_CS) // Queue the connection: if (!ConnRequest->Connect(a_Host, a_Port, a_ConnectCallbacks)) @@ -1088,6 +1106,7 @@ cServerHandlePtr cNetworkSingleton::Listen( { return res; } + cCSLock Lock(m_CS); m_Servers.push_back(res); return res; } @@ -1103,6 +1122,7 @@ bool cNetworkSingleton::HostnameToIP( { try { + cCSLock Lock(m_CS); m_HostnameLookups.push_back(std::make_shared(a_Hostname, a_Callbacks)); } catch (...) @@ -1122,6 +1142,7 @@ bool cNetworkSingleton::IPToHostName( { try { + cCSLock Lock(m_CS); m_IPLookups.push_back(std::make_shared(a_IP, a_Callbacks)); } catch (...) @@ -1165,6 +1186,7 @@ void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self) void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameLookup) { + cCSLock Lock(m_CS); for (auto itr = m_HostnameLookups.begin(), end = m_HostnameLookups.end(); itr != end; ++itr) { if (itr->get() == a_HostnameLookup) @@ -1181,6 +1203,7 @@ void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameL void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup) { + cCSLock Lock(m_CS); for (auto itr = m_IPLookups.begin(), end = m_IPLookups.end(); itr != end; ++itr) { if (itr->get() == a_IPLookup) @@ -1197,6 +1220,7 @@ void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup) void cNetworkSingleton::RemoveLink(const cTCPLinkImpl * a_Link) { + cCSLock Lock(m_CS); for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) { if (itr->get() == a_Link) diff --git a/tests/Network/CMakeLists.txt b/tests/Network/CMakeLists.txt index a63ce7dfe..9d0dcdc24 100644 --- a/tests/Network/CMakeLists.txt +++ b/tests/Network/CMakeLists.txt @@ -6,7 +6,13 @@ include_directories(${CMAKE_SOURCE_DIR}/src/) include_directories(${CMAKE_SOURCE_DIR}/lib/libevent/include) add_definitions(-DTEST_GLOBALS=1) -add_library(Network ${CMAKE_SOURCE_DIR}/src/OSSupport/Network.cpp ${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp) +add_library(Network + ${CMAKE_SOURCE_DIR}/src/OSSupport/Network.cpp + ${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp + ${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp + ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp +) + target_link_libraries(Network event_core event_extra) if (MSVC) target_link_libraries(Network ws2_32.lib) -- cgit v1.2.3