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); 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: 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 // 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) // 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()); Map::DeleteRespawnTimesInDB(save->GetMapId(), save->GetInstanceId());
delete save; if (deleteSave)
{
delete save;
}
return true; return true;
} }
return false; return false;
@@ -216,11 +220,22 @@ void InstanceSave::AddPlayer(ObjectGuid guid)
bool InstanceSave::RemovePlayer(ObjectGuid guid, InstanceSaveMgr* ism) bool InstanceSave::RemovePlayer(ObjectGuid guid, InstanceSaveMgr* ism)
{ {
std::lock_guard<std::mutex> guard(_lock); bool deleteSave = false;
m_playerList.remove(guid); {
std::lock_guard lg(_lock);
m_playerList.remove(guid);
// ism passed as an argument to avoid calling via singleton (might result in a deadlock) // ism passed as an argument to avoid calling via singleton (might result in a deadlock)
return ism->DeleteInstanceSaveIfNeeded(this->GetInstanceId(), false); deleteSave = ism->DeleteInstanceSaveIfNeeded(this, false, false);
}
// Delete save now (avoid mutex memory corruption)
if (deleteSave)
{
delete this;
}
return deleteSave;
} }
void InstanceSaveMgr::LoadInstances() void InstanceSaveMgr::LoadInstances()
@@ -787,7 +802,12 @@ void InstanceSaveMgr::CopyBinds(ObjectGuid from, ObjectGuid to, Player* toPlr)
void InstanceSaveMgr::UnbindAllFor(InstanceSave* save) void InstanceSaveMgr::UnbindAllFor(InstanceSave* save)
{ {
GuidList& pList = save->m_playerList; uint32 mapId = save->GetMapId();
while (!pList.empty()) Difficulty difficulty = save->GetDifficulty();
PlayerUnbindInstance(*(pList.begin()), save->GetMapId(), save->GetDifficulty(), true, ObjectAccessor::FindConnectedPlayer(*(pList.begin()))); 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); InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, bool startup = false);
bool DeleteInstanceSaveIfNeeded(uint32 InstanceId, bool skipMapCheck); 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); InstanceSave* GetInstanceSave(uint32 InstanceId);

View File

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