mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-23 21:46:24 +00:00
fix: Replace static m_botReleaseTimes with per-bot storage to prevent race condition
Fixes a thread safety issue where multiple bots dying in battlegrounds simultaneously would corrupt the shared static unordered_map, causing segmentation faults. Changes: - Remove: static m_botReleaseTimes map from AutoReleaseSpiritAction - Add: bgReleaseAttemptTime member to PlayerbotAI (per-bot storage) - Update: All references to use per-bot storage instead of static map Why this fixes the crash: - Each PlayerbotAI instance is accessed by only one map update thread - No cross-thread access to shared data structures - No mutex/locking required - thread-safe by design - Automatic cleanup when bot is destroyed Thread-safe solution: Per-bot state eliminates race conditions without performance overhead. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -601,6 +601,7 @@ public:
|
|||||||
NewRpgInfo rpgInfo;
|
NewRpgInfo rpgInfo;
|
||||||
NewRpgStatistic rpgStatistic;
|
NewRpgStatistic rpgStatistic;
|
||||||
std::unordered_set<uint32> lowPriorityQuest;
|
std::unordered_set<uint32> lowPriorityQuest;
|
||||||
|
time_t bgReleaseAttemptTime = 0;
|
||||||
|
|
||||||
// Schedules a callback to run once after <delayMs> milliseconds.
|
// Schedules a callback to run once after <delayMs> milliseconds.
|
||||||
void AddTimedEvent(std::function<void()> callback, uint32 delayMs);
|
void AddTimedEvent(std::function<void()> callback, uint32 delayMs);
|
||||||
|
|||||||
@@ -192,12 +192,11 @@ bool AutoReleaseSpiritAction::ShouldDelayBattlegroundRelease() const
|
|||||||
{
|
{
|
||||||
// The below delays release to spirit with 6 seconds.
|
// The below delays release to spirit with 6 seconds.
|
||||||
// This prevents currently casted (ranged) spells to be re-directed to the died bot's ghost.
|
// This prevents currently casted (ranged) spells to be re-directed to the died bot's ghost.
|
||||||
const int32_t botId = bot->GetGUID().GetRawValue();
|
|
||||||
|
|
||||||
// If the bot already is a spirit, erase release time and return true
|
// If the bot already is a spirit, reset release time and return true
|
||||||
if (bot->HasPlayerFlag(PLAYER_FLAGS_GHOST))
|
if (bot->HasPlayerFlag(PLAYER_FLAGS_GHOST))
|
||||||
{
|
{
|
||||||
m_botReleaseTimes.erase(botId);
|
botAI->bgReleaseAttemptTime = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,14 +204,13 @@ bool AutoReleaseSpiritAction::ShouldDelayBattlegroundRelease() const
|
|||||||
const time_t now = time(nullptr);
|
const time_t now = time(nullptr);
|
||||||
constexpr time_t RELEASE_DELAY = 6;
|
constexpr time_t RELEASE_DELAY = 6;
|
||||||
|
|
||||||
auto& lastReleaseTime = m_botReleaseTimes[botId];
|
if (botAI->bgReleaseAttemptTime == 0)
|
||||||
if (lastReleaseTime == 0)
|
botAI->bgReleaseAttemptTime = now;
|
||||||
lastReleaseTime = now;
|
|
||||||
|
|
||||||
if (now - lastReleaseTime < RELEASE_DELAY)
|
if (now - botAI->bgReleaseAttemptTime < RELEASE_DELAY)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_botReleaseTimes.erase(botId);
|
botAI->bgReleaseAttemptTime = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ private:
|
|||||||
bool ShouldAutoRelease() const;
|
bool ShouldAutoRelease() const;
|
||||||
bool ShouldDelayBattlegroundRelease() const;
|
bool ShouldDelayBattlegroundRelease() const;
|
||||||
|
|
||||||
inline static std::unordered_map<uint32_t, time_t> m_botReleaseTimes;
|
|
||||||
time_t m_bgGossipTime = 0;
|
time_t m_bgGossipTime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user