c++concurrencyazerothcoreworld-of-warcrafttrinitycore

Possibility of race conditions in the Azerothcore world process with custom module scripts


I'm writing a command .deposit $Character $moneyDelta with this handler to increase the a character's gold when the character is offline.

    static bool HandleDepositCommand(ChatHandler *handler, PlayerIdentifier player, uint32 moneyDelta)
    {
        ObjectGuid::LowType accountId = player.GetGUID().GetCounter();

        // Player must not be in-game
        if (player.IsConnected()) {
            return false;
        }

        // The player should not log in until this function finishes execution
        // TODO SQL query to increase gold

        return true;
    }

To ensure that the engine's cache doesn't overwrite my SQL write, I imposed a requirement that the player must not be signed in.

Is it possible for the player to connect before HandleDepositCommand() finishes execution? If I understand correctly then the world process is a single threaded while loop where new actions such as new login get queued after HandleDepositCommand().

    ///- While we have not World::m_stopEvent, update the world
    while (!World::IsStopped())
    {
        ++World::m_worldLoopCounter;
        realCurrTime = getMSTime();

        uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
        if (diff < minUpdateDiff)
        {
            uint32 sleepTime = minUpdateDiff - diff;
            if (sleepTime >= halfMaxCoreStuckTime)
                LOG_ERROR("server.worldserver", "WorldUpdateLoop() waiting for {} ms with MaxCoreStuckTime set to {} ms", sleepTime, maxCoreStuckTime);
            // sleep until enough time passes that we can update all timers
            std::this_thread::sleep_for(Milliseconds(sleepTime));
            continue;
        }

        sWorld->Update(diff);
        realPrevTime = realCurrTime;

If not then this is a race condition that can lead to an exploit. The player logs in before the SQL completes overwrites the DB state.


Solution

  • There shouldn't be any race condition since chat commands and player logging both have "thread-unsafe" type which means they are running in the same thread.