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]: Dead lock bug in GameTickScheduler/ServerTimeScheduler #1483

Closed
ShrBox opened this issue Mar 12, 2024 · 0 comments
Closed

[Bug]: Dead lock bug in GameTickScheduler/ServerTimeScheduler #1483

ShrBox opened this issue Mar 12, 2024 · 0 comments
Labels
bug Related to software malfunction priority: critical Requires immediate attention

Comments

@ShrBox
Copy link
Member

ShrBox commented Mar 12, 2024

Describe the bug

std::mutex in Scheduler.h and TickSyncTaskPool.h will be permanently locked while about 20 threads are trying add task which contains adding task into scheduler.
This bug first appear in LiteLDev/LegacyScriptEngine#58

To Reproduce

Insert these code into src\ll\test\ScheduleTest.cpp, the configuration xmake with param --tests=true, compile it.

#include "ll/api/Logger.h"
#include "ll/api/memory/Hook.h"
#include "ll/api/schedule/Scheduler.h"
#include "ll/api/utils/RandomUtils.h"
#include "mc/server/ServerInstance.h"
#include "mc/server/ServerLevel.h"
#include "mc/world/events/ServerInstanceEventCoordinator.h"
#include <chrono>
#include <thread>

// #include "ll/api/thread/GlobalThreadPauser.h"

using namespace ll::schedule;

using namespace ll::chrono_literals;

ll::Logger schedulelogger("Schedule");

SystemTimeScheduler      s;
ServerTimeAsyncScheduler s2;
GameTickScheduler        s3;

#include "mc/network/packet/TextPacket.h"

#include "ll/api/data/DependencyGraph.h"

#include "ll/api/base/Meta.h"

#pragma warning(push)
#pragma warning(disable : 4723)

void deadLockFunc() { // Cause dead lock, random ticks for simulate LSE with a lot of plugns
    s3.add<DelayTask>(ll::chrono::ticks(ll::random_utils::rand(1, 20)), []() {
        schedulelogger.info("dead lock test");
        s3.add<DelayTask>(ll::chrono::ticks(ll::random_utils::rand(1, 20)), []() { deadLockFunc(); });
    });
}

LL_AUTO_TYPE_INSTANCE_HOOK(
    SchedulerTestHook,
    HookPriority::Normal,
    ServerInstanceEventCoordinator,
    &ServerInstanceEventCoordinator::sendServerThreadStarted,
    void,
    ::ServerInstance& ins
) {

    // ll::Logger::setDefaultPlayerOutputFunc([](std::string_view sv) {
    // TextPacket::createRawMessage(sv).sendToClients(); }
    // );
    /*
         s.add<RepeatTask>(100_tick, [&] {
             schedulelogger.info(
                 "hi, 100_tick life {} ramdom {}",
                 ll::chrono::GameTickClock::now().time_since_epoch(),
                 ll::random_utils::rand<uint>()
             );
         });

         s2.add<DelayTask>(1_tick, [&] {
             schedulelogger.info("try GameTime {}", ll::chrono::GameTickClock::now().time_since_epoch());
             s3.add<RepeatTask>(5s, [&] {
                 schedulelogger.warn(
                     "hi, 5s       gt   {} ramdom {}",
                     ll::chrono::GameTickClock::now().time_since_epoch(),
                     ll::random_utils::rand<double>()
                 );
             });
         });

         s2.add<RepeatTask>(0.1min, [&] {
             auto lock = ll::Logger::lock();
             schedulelogger.info(
                 "hi, 0.1min   game {} random {}",
                 ll::chrono::GameTickClock::now().time_since_epoch(),
                 ll::random_utils::rand<int64>()
             );
             auto random  = ll::random_utils::rand<int64>();
             random      /= 0;
             schedulelogger.info("{}", random);
             throw std::system_error(std::error_code(0, ll::error_utils::hresult_category()));
         });

         // s2.add<RepeatTask>(0.3min, [&] {
         //     auto            pause = ll::thread::GlobalThreadPauser{};

         //     schedulelogger.info("hello I paused all threads 1s");

         //     std::this_thread::sleep_for(1s);
         //     schedulelogger.info("hello I paused all threads 2s");

         //     std::this_thread::sleep_for(1s);

         //     schedulelogger.info("hello I resumed all threads");
         // });
     */

    for (unsigned short i = 0; i < 20; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(ll::random_utils::rand(1, 50))); // To simulate LSE with a lot of plugns
        std::thread(deadLockFunc).detach();
    }

    auto                                   l = ll::Logger::lock();
    ll::data::DependencyGraph<std::string> dep;
    dep.emplaceDependencies("a", {"b", "c", "e"});
    dep.emplaceDependencies("b", {"c"});
    dep.emplaceDependencies("c", {"d"});
    dep.emplaceDependencies("e", {"a"});
    const auto& result = dep.sort();
    schedulelogger.info("sorted: {}", result.sorted);
    schedulelogger.info("unsorted: {}", result.unsorted);

    for (auto k : {1, 4, 6}) {
        ll::meta::visitIndex<10>(
            []<size_t N> {
                static ll::Logger lo;
                lo.warn("template N = {}", N);
                return N;
            },
            k
        );
    }

    return origin(ins);
}

#pragma warning(pop)

Expected behavior

Scheduler works fine.

Screenshots

图片
图片
图片
图片

Platform

Windows 11 23H2 22631.3155

Version

0.9.2

Additional context

No response

@ShrBox ShrBox added bug Related to software malfunction priority: critical Requires immediate attention status: in progress Currently being worked on labels Mar 12, 2024
@RimuruChan RimuruChan added status: done and removed status: in progress Currently being worked on labels Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Related to software malfunction priority: critical Requires immediate attention
Development

No branches or pull requests

2 participants