diff options
-rw-r--r-- | src/OSSupport/NetworkSingleton.cpp | 44 | ||||
-rw-r--r-- | src/OSSupport/NetworkSingleton.h | 11 | ||||
-rw-r--r-- | src/main.cpp | 11 | ||||
-rw-r--r-- | tests/Network/EchoServer.cpp | 14 | ||||
-rw-r--r-- | tests/Network/Google.cpp | 15 | ||||
-rw-r--r-- | tests/Network/NameLookup.cpp | 12 |
6 files changed, 90 insertions, 17 deletions
diff --git a/src/OSSupport/NetworkSingleton.cpp b/src/OSSupport/NetworkSingleton.cpp index 92f0604cd..000b17641 100644 --- a/src/OSSupport/NetworkSingleton.cpp +++ b/src/OSSupport/NetworkSingleton.cpp @@ -18,7 +18,8 @@ -cNetworkSingleton::cNetworkSingleton(void) +cNetworkSingleton::cNetworkSingleton(void): + m_HasTerminated(false) { // Windows: initialize networking: #ifdef _WIN32 @@ -72,6 +73,29 @@ cNetworkSingleton::cNetworkSingleton(void) cNetworkSingleton::~cNetworkSingleton() { + // Check that Terminate has been called already: + ASSERT(m_HasTerminated); +} + + + + + +cNetworkSingleton & cNetworkSingleton::Get(void) +{ + static cNetworkSingleton Instance; + return Instance; +} + + + + + +void cNetworkSingleton::Terminate(void) +{ + ASSERT(!m_HasTerminated); + m_HasTerminated = true; + // Wait for the LibEvent event loop to terminate: event_base_loopbreak(m_EventBase); m_EventLoopTerminated.Wait(); @@ -96,16 +120,6 @@ cNetworkSingleton::~cNetworkSingleton() -cNetworkSingleton & cNetworkSingleton::Get(void) -{ - static cNetworkSingleton Instance; - return Instance; -} - - - - - void cNetworkSingleton::LogCallback(int a_Severity, const char * a_Msg) { switch (a_Severity) @@ -138,6 +152,7 @@ void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self) void cNetworkSingleton::AddHostnameLookup(cHostnameLookupPtr a_HostnameLookup) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); m_HostnameLookups.push_back(a_HostnameLookup); } @@ -148,6 +163,7 @@ void cNetworkSingleton::AddHostnameLookup(cHostnameLookupPtr a_HostnameLookup) void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameLookup) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); for (auto itr = m_HostnameLookups.begin(), end = m_HostnameLookups.end(); itr != end; ++itr) { @@ -165,6 +181,7 @@ void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameL void cNetworkSingleton::AddIPLookup(cIPLookupPtr a_IPLookup) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); m_IPLookups.push_back(a_IPLookup); } @@ -175,6 +192,7 @@ void cNetworkSingleton::AddIPLookup(cIPLookupPtr a_IPLookup) void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); for (auto itr = m_IPLookups.begin(), end = m_IPLookups.end(); itr != end; ++itr) { @@ -192,6 +210,7 @@ void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup) void cNetworkSingleton::AddLink(cTCPLinkImplPtr a_Link) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); m_Connections.push_back(a_Link); } @@ -202,6 +221,7 @@ void cNetworkSingleton::AddLink(cTCPLinkImplPtr a_Link) void cNetworkSingleton::RemoveLink(const cTCPLinkImpl * a_Link) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) { @@ -219,6 +239,7 @@ void cNetworkSingleton::RemoveLink(const cTCPLinkImpl * a_Link) void cNetworkSingleton::AddServer(cServerHandleImplPtr a_Server) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); m_Servers.push_back(a_Server); } @@ -229,6 +250,7 @@ void cNetworkSingleton::AddServer(cServerHandleImplPtr a_Server) void cNetworkSingleton::RemoveServer(const cServerHandleImpl * a_Server) { + ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); for (auto itr = m_Servers.begin(), end = m_Servers.end(); itr != end; ++itr) { diff --git a/src/OSSupport/NetworkSingleton.h b/src/OSSupport/NetworkSingleton.h index 1d26fc8f4..e27e19012 100644 --- a/src/OSSupport/NetworkSingleton.h +++ b/src/OSSupport/NetworkSingleton.h @@ -4,7 +4,8 @@ // Declares the cNetworkSingleton class representing the storage for global data pertaining to network API // such as a list of all connections, all listening sockets and the LibEvent dispatch thread. -// This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead +// This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead; +// the only exception being the main app entrypoint that needs to call Terminate before quitting. @@ -48,6 +49,11 @@ public: /** Returns the singleton instance of this class */ static cNetworkSingleton & Get(void); + /** Terminates all network-related threads. + To be used only on app shutdown. + MSVC runtime requires that the LibEvent networking be shut down before the main() function is exitted; this is the way to do it. */ + void Terminate(void); + /** Returns the main LibEvent handle for event registering. */ event_base * GetEventBase(void) { return m_EventBase; } @@ -113,6 +119,9 @@ protected: /** Event that gets signalled when the event loop terminates. */ cEvent m_EventLoopTerminated; + /** Set to true if Terminate has been called. */ + volatile bool m_HasTerminated; + /** Initializes the LibEvent internals. */ cNetworkSingleton(void); diff --git a/src/main.cpp b/src/main.cpp index d4adc1ed9..20609a2f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,13 +11,17 @@ #include <dbghelp.h> #endif // _MSC_VER +#include "OSSupport/NetworkSingleton.h" -bool cRoot::m_TerminateEventRaised = false; // If something has told the server to stop; checked periodically in cRoot -static bool g_ServerTerminated = false; // Set to true when the server terminates, so our CTRL handler can then tell the OS to close the console +/** If something has told the server to stop; checked periodically in cRoot */ +bool cRoot::m_TerminateEventRaised = false; + +/** Set to true when the server terminates, so our CTRL handler can then tell the OS to close the console. */ +static bool g_ServerTerminated = false; /** If set to true, the protocols will log each player's incoming (C->S) communication to a per-connection logfile */ bool g_ShouldLogCommIn; @@ -305,6 +309,9 @@ int main( int argc, char **argv) g_ServerTerminated = true; + // Shutdown all of LibEvent: + cNetworkSingleton::Get().Terminate(); + return EXIT_SUCCESS; } diff --git a/tests/Network/EchoServer.cpp b/tests/Network/EchoServer.cpp index 728db0b7c..5f4b7651d 100644 --- a/tests/Network/EchoServer.cpp +++ b/tests/Network/EchoServer.cpp @@ -7,6 +7,7 @@ #include <iostream> #include <string> #include "OSSupport/Network.h" +#include "OSSupport/NetworkSingleton.h" @@ -98,7 +99,7 @@ class cEchoServerCallbacks: -int main() +void DoTest(void) { LOGD("EchoServer: starting up"); cServerHandlePtr Server = cNetwork::Listen(9876, std::make_shared<cEchoServerCallbacks>()); @@ -119,9 +120,20 @@ int main() Server->Close(); ASSERT(!Server->IsListening()); LOGD("Server has been closed."); +} + + + + + +int main() +{ + DoTest(); printf("Press enter to exit test.\n"); + AString line; std::getline(std::cin, line); + cNetworkSingleton::Get().Terminate(); LOG("Network test finished."); return 0; diff --git a/tests/Network/Google.cpp b/tests/Network/Google.cpp index 2b8830c24..54bfa6de4 100644 --- a/tests/Network/Google.cpp +++ b/tests/Network/Google.cpp @@ -7,6 +7,7 @@ #include <thread> #include "OSSupport/Event.h" #include "OSSupport/Network.h" +#include "OSSupport/NetworkSingleton.h" @@ -96,7 +97,7 @@ public: -int main() +void DoTest(void) { cEvent evtFinish; @@ -109,7 +110,19 @@ int main() LOGD("Connect request has been queued."); evtFinish.Wait(); +} + + + + + +int main() +{ + DoTest(); + + cNetworkSingleton::Get().Terminate(); LOGD("Network test finished"); + return 0; } diff --git a/tests/Network/NameLookup.cpp b/tests/Network/NameLookup.cpp index 822a96baf..16fa8042b 100644 --- a/tests/Network/NameLookup.cpp +++ b/tests/Network/NameLookup.cpp @@ -7,6 +7,7 @@ #include <thread> #include "OSSupport/Event.h" #include "OSSupport/Network.h" +#include "OSSupport/NetworkSingleton.h" @@ -45,7 +46,7 @@ public: -int main() +void DoTest(void) { cEvent evtFinish; @@ -70,7 +71,16 @@ int main() LOGD("IP lookup has been successfully queued"); evtFinish.Wait(); LOGD("IP lookup finished."); +} + + + + +int main() +{ + DoTest(); + cNetworkSingleton::Get().Terminate(); LOGD("Network test finished"); return 0; } |