Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 [Bug] Swiftmend crash fix #2695

Open
Wall-core opened this issue Jun 27, 2024 · 5 comments
Open

🐛 [Bug] Swiftmend crash fix #2695

Wall-core opened this issue Jun 27, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@Wall-core
Copy link
Contributor

Wall-core commented Jun 27, 2024

Swiftmend uses a jank blizzlike structure and has its own special function handling it. this function can crash if you somehow hit a race condition on the dispel mask. It can be fixed by checking the iterator is valid before checking spellproto.
In Unit.cpp:

bool Unit::HasAuraFamily(AuraType type, SpellFamily family, uint64 familyFlag) const
{
    AuraList const& auras = GetAurasByType(type);
    for (const auto& i : auras)
        if (i && i->GetSpellProto() && i->GetSpellProto()->IsFitToFamily(family, familyFlag))
            return true;

    return false;
}
@Wall-core Wall-core added the bug Something isn't working label Jun 27, 2024
@DeltaF1
Copy link
Contributor

DeltaF1 commented Sep 10, 2024

I'm not familiar with how concurrency works in this codebase. Can you elaborate on where the race condition is? Is the problem that the auras list could change and thus auras be destroyed between calling GetAurasByType and IsFitToFamily?

@Wall-core
Copy link
Contributor Author

Wall-core commented Sep 10, 2024

I haven't been able to pinpoint it precisely based on stacktrace but can confirm this fixed the rare crash occurring. It seemingly is related to rapidly tab-targeting units which are friendly/unfriendly while mashing swiftmend. Not sure how the iterator is becoming invalid before being called but it's related to the mask checks used previously.

@DeltaF1
Copy link
Contributor

DeltaF1 commented Sep 10, 2024

Could you post the rest of the code changes you made to fix it? I'm having a hard time figuring out where in the Swiftmend code this added method would be called.

How would you recommend reproducing this issue? You said to switch rapidly between targeting various units while spamming it. Should the friendly units have restoration/rejuvenation on them?

@Wall-core
Copy link
Contributor Author

The only change made is validating the iterator:
if (i && i->GetSpellProto()

@DeltaF1
Copy link
Contributor

DeltaF1 commented Sep 11, 2024

Okay so that would be in here?

Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
// find most short by duration
Aura* targetAura = nullptr;
for (const auto i : RejorRegr)
{
// Regrowth or Rejuvenation
if (i->GetSpellProto()->IsFitToFamily<SPELLFAMILY_DRUID, CF_DRUID_REJUVENATION, CF_DRUID_REGROWTH>())
if (!targetAura || i->GetAuraDuration() < targetAura->GetAuraDuration())
targetAura = i;

I just want to make sure I'm getting it right since I couldn't find the function Unit::HasAuraFamily anywhere in the codebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants