mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Misc: Refactor loading process to remove exit() calls that cause deadlocks because threads are terminated without proper cleanup
This commit is contained in:
@@ -980,15 +980,13 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
|
||||
LOAD_DB2(sWorldMapOverlayStore);
|
||||
LOAD_DB2(sWorldStateExpressionStore);
|
||||
|
||||
#undef LOAD_DB2
|
||||
|
||||
// error checks
|
||||
if (!loadErrors.empty())
|
||||
{
|
||||
sLog->SetSynchronous(); // server will shut down after this, so set sync logging to prevent messages from getting lost
|
||||
|
||||
for (std::string const& error : loadErrors)
|
||||
TC_LOG_ERROR("misc", "{}", error);
|
||||
TC_LOG_FATAL("misc", "{}", error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1002,8 +1000,8 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
|
||||
!sMapStore.LookupEntry(2708) || // last map added in 10.2.5 (53007)
|
||||
!sSpellNameStore.LookupEntry(438878)) // last spell added in 10.2.5 (53007)
|
||||
{
|
||||
TC_LOG_ERROR("misc", "You have _outdated_ DB2 files. Please extract correct versions from current using client.");
|
||||
exit(1);
|
||||
TC_LOG_FATAL("misc", "You have _outdated_ DB2 files. Please extract correct versions from current using client.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (AreaGroupMemberEntry const* areaGroupMember : sAreaGroupMemberStore)
|
||||
|
||||
@@ -1730,7 +1730,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
}
|
||||
|
||||
/// Initialize the World
|
||||
void World::SetInitialWorldSettings()
|
||||
bool World::SetInitialWorldSettings()
|
||||
{
|
||||
sLog->SetRealmId(realm.Id.Realm);
|
||||
|
||||
@@ -1769,7 +1769,7 @@ void World::SetInitialWorldSettings()
|
||||
!TerrainMgr::ExistMapAndVMap(530, -3961.64f, -13931.2f))))
|
||||
{
|
||||
TC_LOG_FATAL("server.loading", "Unable to load map and vmap data for starting zones - server shutting down!");
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialize pool manager
|
||||
@@ -1782,7 +1782,7 @@ void World::SetInitialWorldSettings()
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading Trinity strings...");
|
||||
if (!sObjectMgr->LoadTrinityStrings())
|
||||
exit(1); // Error message displayed in function already
|
||||
return false; // Error message displayed in function already
|
||||
|
||||
///- Update the realm entry in the database with the realm type from the config file
|
||||
//No SQL injection as values are treated as integers
|
||||
@@ -1799,14 +1799,14 @@ void World::SetInitialWorldSettings()
|
||||
if (!(m_availableDbcLocaleMask & (1 << m_defaultDbcLocale)))
|
||||
{
|
||||
TC_LOG_FATAL("server.loading", "Unable to load db2 files for {} locale specified in DBC.Locale config!", localeNames[m_defaultDbcLocale]);
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading GameObject models...");
|
||||
if (!LoadGameObjectModelList(m_dataPath))
|
||||
{
|
||||
TC_LOG_FATAL("server.loading", "Unable to load gameobject models (part of vmaps), objects using WMO models will crash the client - server shutting down!");
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
TC_LOG_INFO("misc", "Loading hotfix blobs...");
|
||||
@@ -2537,6 +2537,7 @@ void World::SetInitialWorldSettings()
|
||||
TC_LOG_INFO("server.worldserver", "World initialized in {} minutes {} seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
|
||||
|
||||
TC_METRIC_EVENT("events", "World initialized", "World initialized in " + std::to_string(startupDuration / 60000) + " minutes " + std::to_string((startupDuration % 60000) / 1000) + " seconds");
|
||||
return true;
|
||||
}
|
||||
|
||||
void World::SetForcedWarModeFactionBalanceState(TeamId team, int32 reward)
|
||||
|
||||
@@ -648,7 +648,7 @@ class TC_GAME_API World
|
||||
return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl * 5;
|
||||
}
|
||||
|
||||
void SetInitialWorldSettings();
|
||||
bool SetInitialWorldSettings();
|
||||
void LoadConfigSettings(bool reload = false);
|
||||
|
||||
void SendWorldText(uint32 string_id, ...);
|
||||
|
||||
@@ -338,7 +338,8 @@ extern int main(int argc, char** argv)
|
||||
|
||||
// Initialize the World
|
||||
sSecretMgr->Initialize(SECRET_OWNER_WORLDSERVER);
|
||||
sWorld->SetInitialWorldSettings();
|
||||
if (!sWorld->SetInitialWorldSettings())
|
||||
return 1;
|
||||
|
||||
auto mapManagementHandle = Trinity::make_unique_ptr_with_deleter(&dummy, [](void*)
|
||||
{
|
||||
@@ -359,7 +360,12 @@ extern int main(int argc, char** argv)
|
||||
// Start soap serving thread if enabled
|
||||
std::unique_ptr<std::thread, ShutdownTCSoapThread> soapThread;
|
||||
if (sConfigMgr->GetBoolDefault("SOAP.Enabled", false))
|
||||
soapThread.reset(new std::thread(TCSoapThread, sConfigMgr->GetStringDefault("SOAP.IP", "127.0.0.1"), uint16(sConfigMgr->GetIntDefault("SOAP.Port", 7878))));
|
||||
{
|
||||
if (std::thread* soap = CreateSoapThread(sConfigMgr->GetStringDefault("SOAP.IP", "127.0.0.1"), uint16(sConfigMgr->GetIntDefault("SOAP.Port", 7878))))
|
||||
soapThread.reset(soap);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Launch the worldserver listener socket
|
||||
uint16 worldPort = uint16(sWorld->getIntConfig(CONFIG_PORT_WORLD));
|
||||
|
||||
@@ -16,49 +16,57 @@
|
||||
*/
|
||||
|
||||
#include "TCSoap.h"
|
||||
#include "soapH.h"
|
||||
#include "soapStub.h"
|
||||
#include "AccountMgr.h"
|
||||
#include "IpAddress.h"
|
||||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "Realm.h"
|
||||
#include "World.h"
|
||||
#include "AccountMgr.h"
|
||||
#include "Log.h"
|
||||
#include "soapH.h"
|
||||
#include "soapStub.h"
|
||||
|
||||
void TCSoapThread(const std::string& host, uint16 port)
|
||||
std::thread* CreateSoapThread(const std::string& host, uint16 port)
|
||||
{
|
||||
struct soap soap;
|
||||
soap_init(&soap);
|
||||
soap_set_imode(&soap, SOAP_C_UTFSTRING);
|
||||
soap_set_omode(&soap, SOAP_C_UTFSTRING);
|
||||
auto soap = Trinity::make_unique_ptr_with_deleter<struct soap*>(new struct soap(), [](struct soap* soap)
|
||||
{
|
||||
soap_destroy(soap);
|
||||
soap_end(soap);
|
||||
soap_done(soap);
|
||||
delete soap;
|
||||
});
|
||||
|
||||
soap_init(soap.get());
|
||||
soap_set_imode(soap.get(), SOAP_C_UTFSTRING);
|
||||
soap_set_omode(soap.get(), SOAP_C_UTFSTRING);
|
||||
|
||||
#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
|
||||
soap.bind_flags = SO_REUSEADDR;
|
||||
soap->bind_flags = SO_REUSEADDR;
|
||||
#endif
|
||||
|
||||
// check every 3 seconds if world ended
|
||||
soap.accept_timeout = 3;
|
||||
soap.recv_timeout = 5;
|
||||
soap.send_timeout = 5;
|
||||
if (!soap_valid_socket(soap_bind(&soap, host.c_str(), port, 100)))
|
||||
soap->accept_timeout = 3;
|
||||
soap->recv_timeout = 5;
|
||||
soap->send_timeout = 5;
|
||||
if (!soap_valid_socket(soap_bind(soap.get(), host.c_str(), port, 100)))
|
||||
{
|
||||
TC_LOG_ERROR("network.soap", "Couldn't bind to {}:{}", host, port);
|
||||
exit(-1);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TC_LOG_INFO("network.soap", "Bound to http://{}:{}", host, port);
|
||||
|
||||
while (!World::IsStopped())
|
||||
return new std::thread([soap = std::move(soap)]
|
||||
{
|
||||
if (!soap_valid_socket(soap_accept(&soap)))
|
||||
continue; // ran into an accept timeout
|
||||
while (!World::IsStopped())
|
||||
{
|
||||
if (!soap_valid_socket(soap_accept(soap.get())))
|
||||
continue; // ran into an accept timeout
|
||||
|
||||
TC_LOG_DEBUG("network.soap", "Accepted connection from IP={}.{}.{}.{}", (int)(soap.ip>>24)&0xFF, (int)(soap.ip>>16)&0xFF, (int)(soap.ip>>8)&0xFF, (int)soap.ip&0xFF);
|
||||
struct soap* thread_soap = soap_copy(&soap);// make a safe copy
|
||||
process_message(thread_soap);
|
||||
}
|
||||
|
||||
soap_destroy(&soap);
|
||||
soap_end(&soap);
|
||||
soap_done(&soap);
|
||||
struct soap* thread_soap = soap_copy(soap.get());// make a safe copy
|
||||
TC_LOG_DEBUG("network.soap", "Accepted connection from IP={}", Trinity::Net::make_address_v4(thread_soap->ip).to_string());
|
||||
process_message(thread_soap);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void process_message(struct soap* soap_message)
|
||||
|
||||
@@ -21,9 +21,10 @@
|
||||
#include "Define.h"
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
void process_message(struct soap* soap_message);
|
||||
void TCSoapThread(const std::string& host, uint16 port);
|
||||
std::thread* CreateSoapThread(const std::string& host, uint16 port);
|
||||
|
||||
class SOAPCommand
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user