aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiacomo Pozzoni <giacomopoz@gmail.com>2020-05-16 09:06:03 +0000
committerShauren <shauren.trinity@gmail.com>2022-01-04 15:33:04 +0100
commit9cb01a79046fce3f76835bb68bf66e4f3079e4bc (patch)
treec5efcb9271d782e828399e197f6077e54b791c59
parent2256735a7765bbbd6383739b988db84761520233 (diff)
Fixes/3.3.5 aura infinite loop (#24631)
* Core/Auras: Attempt to fix infinite loop with aura 18950 on map unload * Core/Auras: Log a detailed error and assert when failing to remove all auras after a few tries * Code cleanup * Fix build warnings * Fix more build warnings (cherry picked from commit bd2d60c2676a1d7e843a2a5673b8216bad0768c7)
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp33
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp43
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp8
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h2
4 files changed, 68 insertions, 18 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 6537c31c890..c1ff6556ed4 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -4035,7 +4035,7 @@ void Unit::RemoveAllAuras()
{
// this may be a dead loop if some events on aura remove will continiously apply aura on remove
// we want to have all auras removed, so use your brain when linking events
- while (!m_appliedAuras.empty() || !m_ownedAuras.empty())
+ for (int counter = 0; !m_appliedAuras.empty() || !m_ownedAuras.empty(); counter++)
{
AuraApplicationMap::iterator aurAppIter;
for (aurAppIter = m_appliedAuras.begin(); aurAppIter != m_appliedAuras.end();)
@@ -4044,6 +4044,37 @@ void Unit::RemoveAllAuras()
AuraMap::iterator aurIter;
for (aurIter = m_ownedAuras.begin(); aurIter != m_ownedAuras.end();)
RemoveOwnedAura(aurIter);
+
+ const int maxIteration = 50;
+ // give this loop a few tries, if there are still auras then log as much information as possible
+ if (counter >= maxIteration)
+ {
+ std::stringstream sstr;
+ sstr << "Unit::RemoveAllAuras() iterated " << maxIteration << " times already but there are still "
+ << m_appliedAuras.size() << " m_appliedAuras and " << m_ownedAuras.size() << " m_ownedAuras. Details:" << "\n";
+ sstr << GetDebugInfo() << "\n";
+
+ if (!m_appliedAuras.empty())
+ {
+ sstr << "m_appliedAuras:" << "\n";
+
+ for (std::pair<uint32 const, AuraApplication*>& auraAppPair : m_appliedAuras)
+ sstr << auraAppPair.second->GetDebugInfo() << "\n";
+ }
+
+ if (!m_ownedAuras.empty())
+ {
+ sstr << "m_ownedAuras:" << "\n";
+
+ for (std::pair<uint32 const, Aura*>& auraPair : m_ownedAuras)
+ sstr << auraPair.second->GetDebugInfo() << "\n";
+ }
+
+ TC_LOG_ERROR("entities.unit", "%s", sstr.str().c_str());
+ ABORT_MSG("%s", sstr.str().c_str());
+
+ break;
+ }
}
}
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index b04f6ca4a54..c03f5d38bb2 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1406,8 +1406,9 @@ void AuraEffect::HandleModInvisibilityDetect(AuraApplication const* aurApp, uint
target->m_invisibilityDetect.AddValue(type, -GetAmount());
}
- // call functions which may have additional effects after chainging state of unit
- target->UpdateObjectVisibility();
+ // call functions which may have additional effects after changing state of unit
+ if (target->IsInWorld())
+ target->UpdateObjectVisibility();
}
void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1457,13 +1458,15 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode
target->m_invisibility.AddValue(type, -GetAmount());
}
- // call functions which may have additional effects after chainging state of unit
+ // call functions which may have additional effects after changing state of unit
if (apply && (mode & AURA_EFFECT_HANDLE_REAL))
{
// drop flag at invisibiliy in bg
target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis);
}
- target->UpdateObjectVisibility();
+
+ if (target->IsInWorld())
+ target->UpdateObjectVisibility();
}
void AuraEffect::HandleModStealthDetect(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1487,8 +1490,9 @@ void AuraEffect::HandleModStealthDetect(AuraApplication const* aurApp, uint8 mod
target->m_stealthDetect.AddValue(type, -GetAmount());
}
- // call functions which may have additional effects after chainging state of unit
- target->UpdateObjectVisibility();
+ // call functions which may have additional effects after changing state of unit
+ if (target->IsInWorld())
+ target->UpdateObjectVisibility();
}
void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1522,13 +1526,15 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo
}
}
- // call functions which may have additional effects after chainging state of unit
+ // call functions which may have additional effects after changing state of unit
if (apply && (mode & AURA_EFFECT_HANDLE_REAL))
{
// drop flag at stealth in bg
target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis);
}
- target->UpdateObjectVisibility();
+
+ if (target->IsInWorld())
+ target->UpdateObjectVisibility();
}
void AuraEffect::HandleModStealthLevel(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1544,8 +1550,9 @@ void AuraEffect::HandleModStealthLevel(AuraApplication const* aurApp, uint8 mode
else
target->m_stealth.AddValue(type, -GetAmount());
- // call functions which may have additional effects after chainging state of unit
- target->UpdateObjectVisibility();
+ // call functions which may have additional effects after changing state of unit
+ if (target->IsInWorld())
+ target->UpdateObjectVisibility();
}
void AuraEffect::HandleDetectAmore(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1604,7 +1611,7 @@ void AuraEffect::HandleSpiritOfRedemption(AuraApplication const* aurApp, uint8 m
}
// die at aura end
else if (target->IsAlive())
- // call functions which may have additional effects after chainging state of unit
+ // call functions which may have additional effects after changing state of unit
target->setDeathState(JUST_DIED);
}
@@ -2164,7 +2171,7 @@ void AuraEffect::HandleModUnattackable(AuraApplication const* aurApp, uint8 mode
else
target->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE_2);
- // call functions which may have additional effects after chainging state of unit
+ // call functions which may have additional effects after changing state of unit
if (apply && (mode & AURA_EFFECT_HANDLE_REAL))
{
if (target->GetMap()->IsDungeon())
@@ -2261,7 +2268,7 @@ void AuraEffect::HandleAuraModSilence(AuraApplication const* aurApp, uint8 mode,
{
target->AddUnitFlag(UNIT_FLAG_SILENCED);
- // call functions which may have additional effects after chainging state of unit
+ // call functions which may have additional effects after changing state of unit
// Stop cast only spells vs PreventionType & SPELL_PREVENTION_TYPE_SILENCE
for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i)))
@@ -2409,8 +2416,9 @@ void AuraEffect::HandleAuraModStalked(AuraApplication const* aurApp, uint8 mode,
target->RemoveDynamicFlag(UNIT_DYNFLAG_TRACK_UNIT);
}
- // call functions which may have additional effects after chainging state of unit
- target->UpdateObjectVisibility();
+ // call functions which may have additional effects after changing state of unit
+ if (target->IsInWorld())
+ target->UpdateObjectVisibility();
}
void AuraEffect::HandleAuraUntrackable(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -5051,8 +5059,9 @@ void AuraEffect::HandleAuraModFakeInebriation(AuraApplication const* aurApp, uin
target->m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK);
}
- // call functions which may have additional effects after chainging state of unit
- target->UpdateObjectVisibility();
+ // call functions which may have additional effects after changing state of unit
+ if (target->IsInWorld())
+ target->UpdateObjectVisibility();
}
void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 7dbb0580ca0..d9d6a9091b7 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -291,6 +291,14 @@ void AuraApplication::ClientUpdate(bool remove)
_target->SendMessageToSet(update.Write(), true);
}
+std::string AuraApplication::GetDebugInfo() const
+{
+ std::stringstream sstr;
+ sstr << "Base: " << (GetBase() ? GetBase()->GetDebugInfo() : "NULL")
+ << "\nTarget: " << (GetTarget() ? GetTarget()->GetDebugInfo() : "NULL");
+ return sstr.str();
+}
+
uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availableEffectMask, WorldObject* owner)
{
ASSERT_NODEBUGINFO(spellProto);
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index ee0e79b2604..212e44ececd 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -92,6 +92,8 @@ class TC_GAME_API AuraApplication
bool IsNeedClientUpdate() const { return _needClientUpdate; }
void BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo, bool remove);
void ClientUpdate(bool remove = false);
+
+ std::string GetDebugInfo() const;
};
// Structure representing database aura primary key fields