Sort out server destruction order

fixes #14421
This commit is contained in:
sfan5 2024-03-01 20:02:58 +01:00
parent 4d24537590
commit ef0009aea7
4 changed files with 40 additions and 31 deletions

@ -1328,8 +1328,8 @@ ServerMap::~ServerMap()
} }
catch(std::exception &e) catch(std::exception &e)
{ {
infostream<<"ServerMap: Failed to save map to "<<m_savedir errorstream << "ServerMap: Failed to save map to " << m_savedir
<<", exception: "<<e.what()<<std::endl; << ", exception: " << e.what() << std::endl;
} }
/* /*

@ -321,7 +321,6 @@ Server::Server(
Server::~Server() Server::~Server()
{ {
// Send shutdown message // Send shutdown message
SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE,
L"*** Server shutting down")); L"*** Server shutting down"));
@ -349,18 +348,31 @@ Server::~Server()
actionstream << "Server: Shutting down" << std::endl; actionstream << "Server: Shutting down" << std::endl;
// Do this before stopping the server in case mapgen callbacks need to access // Stop server step from happening
// server-controlled resources (like ModStorages). Also do them before if (m_thread) {
// shutdown callbacks since they may modify state that is finalized in a stop();
delete m_thread;
}
// Stop all emerge activity and finish off mapgen callbacks. Do this before
// shutdown callbacks since there may be state that is finalized in a
// callback. // callback.
// Note: The emerge manager is not deleted yet because further code can
// still interact with map loading.
if (m_emerge) if (m_emerge)
m_emerge->stopThreads(); m_emerge->stopThreads();
if (m_env) { if (m_env) {
MutexAutoLock envlock(m_env_mutex); MutexAutoLock envlock(m_env_mutex);
// Execute script shutdown hooks try {
infostream << "Executing shutdown hooks" << std::endl; // Empty out the environment, this can also invoke callbacks.
m_env->deactivateBlocksAndObjects();
} catch (ModError &e) {
addShutdownError(e);
}
infostream << "Server: Executing shutdown hooks" << std::endl;
try { try {
m_script->on_shutdown(); m_script->on_shutdown();
} catch (ModError &e) { } catch (ModError &e) {
@ -369,12 +381,10 @@ Server::~Server()
infostream << "Server: Saving environment metadata" << std::endl; infostream << "Server: Saving environment metadata" << std::endl;
m_env->saveMeta(); m_env->saveMeta();
}
// Stop threads // Note that this also deletes and saves the map.
if (m_thread) { delete m_env;
stop(); m_env = nullptr;
delete m_thread;
} }
// Write any changes before deletion. // Write any changes before deletion.
@ -388,22 +398,18 @@ Server::~Server()
} }
} }
// Delete things in the reverse order of creation // Delete the rest in the reverse order of creation
delete m_game_settings;
delete m_emerge; delete m_emerge;
delete m_env;
delete m_rollback;
delete m_mod_storage_database;
delete m_banmanager; delete m_banmanager;
delete m_mod_storage_database;
delete m_startup_server_map; // if available
delete m_script;
delete m_rollback;
delete m_itemdef; delete m_itemdef;
delete m_nodedef; delete m_nodedef;
delete m_craftdef; delete m_craftdef;
// Deinitialize scripting
infostream << "Server: Deinitializing scripting" << std::endl;
delete m_script;
delete m_startup_server_map; // if available
delete m_game_settings;
while (!m_unsent_map_edit_queue.empty()) { while (!m_unsent_map_edit_queue.empty()) {
delete m_unsent_map_edit_queue.front(); delete m_unsent_map_edit_queue.front();
m_unsent_map_edit_queue.pop(); m_unsent_map_edit_queue.pop();
@ -582,7 +588,7 @@ void Server::start()
void Server::stop() void Server::stop()
{ {
infostream<<"Server: Stopping and waiting threads"<<std::endl; infostream<<"Server: Stopping and waiting for threads"<<std::endl;
// Stop threads (set run=false first so both start stopping) // Stop threads (set run=false first so both start stopping)
m_thread->stop(); m_thread->stop();

@ -534,18 +534,18 @@ void ServerEnvironment::init()
} }
} }
ServerEnvironment::~ServerEnvironment() void ServerEnvironment::deactivateBlocksAndObjects()
{ {
// Clear active block list. // Clear active block list.
// This makes the next one delete all active objects. // This makes the next one delete all active objects.
m_active_blocks.clear(); m_active_blocks.clear();
try { deactivateFarObjects(true);
// Convert all objects to static and delete the active objects }
deactivateFarObjects(true);
} catch (ModError &e) { ServerEnvironment::~ServerEnvironment()
m_server->addShutdownError(e); {
} assert(m_active_blocks.size() == 0); // deactivateBlocksAndObjects does this
// Drop/delete map // Drop/delete map
if (m_map) if (m_map)

@ -363,6 +363,9 @@ public:
// Clear objects, loading and going through every MapBlock // Clear objects, loading and going through every MapBlock
void clearObjects(ClearObjectsMode mode); void clearObjects(ClearObjectsMode mode);
// to be called before destructor
void deactivateBlocksAndObjects();
// This makes stuff happen // This makes stuff happen
void step(f32 dtime); void step(f32 dtime);