Fix: Prevent concurrent bot initializations during .playerbot init= commands (#1227)

A simple RAII mechanism with std::unordered_set<ObjectGuid> to track GUIDs of init bots.

Ensures that multiple threads or calls do not execute PlayerbotFactory::Randomize() logic at the same time for the same bot.
This commit is contained in:
EricksOliveira
2025-04-27 07:47:02 -03:00
committed by GitHub
parent a5e0e6f5cf
commit 34a888978e

View File

@@ -9,6 +9,7 @@
#include <cstring>
#include <istream>
#include <string>
#include <unordered_set>
#include "ChannelMgr.h"
#include "CharacterCache.h"
@@ -34,6 +35,34 @@
#include "PlayerbotDbStore.h"
#include "WorldSessionMgr.h"
class BotInitGuard
{
public:
BotInitGuard(ObjectGuid guid) : guid(guid), active(false)
{
if (!botsBeingInitialized.contains(guid))
{
botsBeingInitialized.insert(guid);
active = true;
}
}
~BotInitGuard()
{
if (active)
botsBeingInitialized.erase(guid);
}
bool IsLocked() const { return !active; }
private:
ObjectGuid guid;
bool active;
static std::unordered_set<ObjectGuid> botsBeingInitialized;
};
std::unordered_set<ObjectGuid> BotInitGuard::botsBeingInitialized;
PlayerbotHolder::PlayerbotHolder() : PlayerbotAIBase(false) {}
class PlayerbotLoginQueryHolder : public LoginQueryHolder
{
@@ -696,6 +725,14 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
{
return "The command is not allowed, use init=auto instead.";
}
// Use boot guard
BotInitGuard guard(bot->GetGUID());
if (guard.IsLocked())
{
return "Initialization already in progress, please wait.";
}
int gs;
if (cmd == "init=white" || cmd == "init=common")
{