Added network termination called at app exit.
This fixes a crash in MSVC runtime caused by joining a thread in a global var's destructor.
This commit is contained in:
parent
9a2200f8bb
commit
053362e604
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
13
src/main.cpp
13
src/main.cpp
@ -11,14 +11,18 @@
|
||||
#include <dbghelp.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
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
|
||||
#include "OSSupport/NetworkSingleton.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user