From 8418c7ba9a8528e6491903e532ae8bc4a3ffa223 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sat, 27 Apr 2013 21:05:34 +0000 Subject: [PATCH] Fixed a deadlock FS #363 git-svn-id: http://mc-server.googlecode.com/svn/trunk@1421 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Root.cpp | 23 +++++++++++++++++++++++ source/Root.h | 41 ++++++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/source/Root.cpp b/source/Root.cpp index ea33afe7e..1e7f48cc9 100644 --- a/source/Root.cpp +++ b/source/Root.cpp @@ -349,6 +349,18 @@ bool cRoot::ForEachWorld(cWorldListCallback & a_Callback) void cRoot::TickWorlds(float a_Dt) { + // Execute any pending commands: + AStringVector PendingCommands; + { + cCSLock Lock(m_CSPendingCommands); + std::swap(PendingCommands, m_PendingCommands); + } + for (AStringVector::iterator itr = PendingCommands.begin(), end = PendingCommands.end(); itr != end; ++itr) + { + DoExecuteConsoleCommand(*itr); + } + + // Tick the worlds: for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr) { itr->second->Tick(a_Dt); @@ -360,6 +372,17 @@ void cRoot::TickWorlds(float a_Dt) void cRoot::ExecuteConsoleCommand(const AString & a_Cmd) +{ + // Put the command into a queue (Alleviates FS #363): + cCSLock Lock(m_CSPendingCommands); + m_PendingCommands.push_back(a_Cmd); +} + + + + + +void cRoot::DoExecuteConsoleCommand(const AString & a_Cmd) { LOG("Executing console command: \"%s\"", a_Cmd.c_str()); m_Server->ExecuteConsoleCommand(a_Cmd); diff --git a/source/Root.h b/source/Root.h index d3a06354f..9f94c4df3 100644 --- a/source/Root.h +++ b/source/Root.h @@ -62,7 +62,7 @@ public: cPluginManager * GetPluginManager (void) { return m_PluginManager; } // tolua_export cAuthenticator & GetAuthenticator (void) { return m_Authenticator; } - /// Executes a console command through the cServer class; does special handling for "stop" and "restart". + /// Queues a console command for execution through the cServer class; does special handling for "stop" and "restart". void ExecuteConsoleCommand(const AString & a_Cmd); // tolua_export /// Kicks the user, no matter in what world they are. Used from cAuthenticator @@ -89,19 +89,14 @@ public: static AString GetProtocolVersionTextFromInt(int a_ProtocolVersionNum); // tolua_export private: - void LoadGlobalSettings(); + typedef std::map< AString, cWorld* > WorldMap; + cWorld* m_pDefaultWorld; + WorldMap m_WorldsByName; + + cCriticalSection m_CSPendingCommands; + AStringVector m_PendingCommands; - /// Loads the worlds from settings.ini, creates the worldmap - void LoadWorlds(void); - - /// Starts each world's life - void StartWorlds(void); - - /// Stops each world's threads, so that it's safe to unload them - void StopWorlds(void); - - /// Unloads all worlds from memory - void UnloadWorlds(void); + cThread * m_InputThread; cServer * m_Server; cMonsterConfig * m_MonsterConfig; @@ -118,11 +113,23 @@ private: bool m_bStop; bool m_bRestart; - typedef std::map< AString, cWorld* > WorldMap; - cWorld* m_pDefaultWorld; - WorldMap m_WorldsByName; + void LoadGlobalSettings(); + + /// Loads the worlds from settings.ini, creates the worldmap + void LoadWorlds(void); + + /// Starts each world's life + void StartWorlds(void); + + /// Stops each world's threads, so that it's safe to unload them + void StopWorlds(void); + + /// Unloads all worlds from memory + void UnloadWorlds(void); + + /// Does the actual work of executing a command + void DoExecuteConsoleCommand(const AString & a_Cmd); - cThread* m_InputThread; static void InputThread(void* a_Params); static cRoot* s_Root;