diff --git a/include/LuaAPI.h b/include/LuaAPI.h index d18a27d..115d7ec 100644 --- a/include/LuaAPI.h +++ b/include/LuaAPI.h @@ -4,6 +4,8 @@ #include namespace LuaAPI { +int PanicHandler(lua_State* State); + void Print(sol::variadic_args); namespace MP { extern TLuaEngine* Engine; diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index eb67c48..360dc04 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -98,6 +98,7 @@ private: void CollectAndInitPlugins(); void InitializePlugin(const fs::path& Folder, const TLuaPluginConfig& Config); void FindAndParseConfig(const fs::path& Folder, TLuaPluginConfig& Config); + size_t CalculateMemoryUsage(); class StateThreadData : IThreaded { public: @@ -109,6 +110,7 @@ private: void RegisterEvent(const std::string& EventName, const std::string& FunctionName); void AddPath(const fs::path& Path); // to be added to path and cpath void operator()() override; + sol::state_view State() { return sol::state_view(mState); } private: sol::table Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs); diff --git a/src/LuaAPI.cpp b/src/LuaAPI.cpp index 01f4db0..14cf22c 100644 --- a/src/LuaAPI.cpp +++ b/src/LuaAPI.cpp @@ -246,3 +246,8 @@ void LuaAPI::MP::PrintRaw(sol::variadic_args Args) { } Application::Console().WriteRaw(ToPrint); } + +int LuaAPI::PanicHandler(lua_State* State) { + beammp_lua_error("PANIC: " + sol::stack::get(State, 1)); + return 0; +} diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 820a44e..663f9b7 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -44,10 +44,20 @@ void TLuaEngine::operator()() { } // this thread handles timers while (!mShutdown) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::seconds(1)); + beammp_debug("Lua uses " + std::to_string(CalculateMemoryUsage()) + " B of memory"); } } +size_t TLuaEngine::CalculateMemoryUsage() { + size_t Usage = 0; + std::unique_lock Lock(mLuaStatesMutex); + for (auto& State : mLuaStates) { + Usage += State.second->State().memory_used(); + } + return Usage; +} + void TLuaEngine::WaitForAll(std::vector>& Results) { for (const auto& Result : Results) { while (!Result->Ready) { @@ -269,8 +279,13 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi , mStateId(StateId) , mState(luaL_newstate()) , mEngine(&Engine) { + if (!mState) { + beammp_error("failed to create lua state for \"" + StateId + "\""); + return; + } luaL_openlibs(mState); sol::state_view StateView(mState); + lua_atpanic(mState, LuaAPI::PanicHandler); // StateView.globals()["package"].get() StateView.set_function("print", &LuaAPI::Print); StateView.set_function("exit", &Application::GracefullyShutdown); @@ -317,6 +332,9 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi }); MPTable.set_function("IsPlayerGuest", &LuaAPI::MP::IsPlayerGuest); MPTable.set_function("DropPlayer", &LuaAPI::MP::DropPlayer); + MPTable.set_function("GetStateMemoryUsage", [&]() -> size_t { + return mStateView.memory_used(); + }); MPTable.set_function("GetPlayerIdentifiers", [&](int ID) -> sol::table { return Lua_GetPlayerIdentifiers(ID); });