fix(Core): Crash related to reset instances (#11003)

This commit is contained in:
UltraNix
2022-03-18 23:32:28 +01:00
committed by GitHub
parent 52427b4ec2
commit 3c9e8d4eb1
3 changed files with 31 additions and 10 deletions

View File

@@ -116,7 +116,7 @@ bool InstanceSaveMgr::DeleteInstanceSaveIfNeeded(uint32 InstanceId, bool skipMap
return DeleteInstanceSaveIfNeeded(GetInstanceSave(InstanceId), skipMapCheck);
}
bool InstanceSaveMgr::DeleteInstanceSaveIfNeeded(InstanceSave* save, bool skipMapCheck)
bool InstanceSaveMgr::DeleteInstanceSaveIfNeeded(InstanceSave* save, bool skipMapCheck, bool deleteSave /*= true*/)
{
// pussywizard: save is removed only when there are no more players bound AND the map doesn't exist
// pussywizard: this function is called when unbinding a player and when unloading a map
@@ -136,7 +136,11 @@ bool InstanceSaveMgr::DeleteInstanceSaveIfNeeded(InstanceSave* save, bool skipMa
// clear respawn times (if map is loaded do it just to be sure, if already unloaded it won't do it by itself)
Map::DeleteRespawnTimesInDB(save->GetMapId(), save->GetInstanceId());
delete save;
if (deleteSave)
{
delete save;
}
return true;
}
return false;
@@ -216,11 +220,22 @@ void InstanceSave::AddPlayer(ObjectGuid guid)
bool InstanceSave::RemovePlayer(ObjectGuid guid, InstanceSaveMgr* ism)
{
std::lock_guard<std::mutex> guard(_lock);
m_playerList.remove(guid);
bool deleteSave = false;
{
std::lock_guard lg(_lock);
m_playerList.remove(guid);
// ism passed as an argument to avoid calling via singleton (might result in a deadlock)
return ism->DeleteInstanceSaveIfNeeded(this->GetInstanceId(), false);
// ism passed as an argument to avoid calling via singleton (might result in a deadlock)
deleteSave = ism->DeleteInstanceSaveIfNeeded(this, false, false);
}
// Delete save now (avoid mutex memory corruption)
if (deleteSave)
{
delete this;
}
return deleteSave;
}
void InstanceSaveMgr::LoadInstances()
@@ -787,7 +802,12 @@ void InstanceSaveMgr::CopyBinds(ObjectGuid from, ObjectGuid to, Player* toPlr)
void InstanceSaveMgr::UnbindAllFor(InstanceSave* save)
{
GuidList& pList = save->m_playerList;
while (!pList.empty())
PlayerUnbindInstance(*(pList.begin()), save->GetMapId(), save->GetDifficulty(), true, ObjectAccessor::FindConnectedPlayer(*(pList.begin())));
uint32 mapId = save->GetMapId();
Difficulty difficulty = save->GetDifficulty();
GuidList players = save->m_playerList;
for (ObjectGuid const& guid : players)
{
PlayerUnbindInstance(guid, mapId, difficulty, true, ObjectAccessor::FindConnectedPlayer(guid));
}
}

View File

@@ -166,7 +166,7 @@ public:
InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, bool startup = false);
bool DeleteInstanceSaveIfNeeded(uint32 InstanceId, bool skipMapCheck);
bool DeleteInstanceSaveIfNeeded(InstanceSave* save, bool skipMapCheck);
bool DeleteInstanceSaveIfNeeded(InstanceSave* save, bool skipMapCheck, bool deleteSave = true);
InstanceSave* GetInstanceSave(uint32 InstanceId);

View File

@@ -2797,6 +2797,7 @@ InstanceMap::~InstanceMap()
{
delete instance_data;
instance_data = nullptr;
sInstanceSaveMgr->DeleteInstanceSaveIfNeeded(GetInstanceId(), true);
}
void InstanceMap::InitVisibilityDistance()