summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/OSSupport/NetworkSingleton.cpp44
-rw-r--r--src/OSSupport/NetworkSingleton.h11
-rw-r--r--src/main.cpp11
3 files changed, 52 insertions, 14 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;
}