From 706cabeebddb414be5537873d95f9a8c57fd425b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 18 Aug 2024 23:26:37 +0300 Subject: [PATCH] add lua::stackguard --- src/logic/scripting/lua/lua_commons.hpp | 24 +++++++++++++++++-- .../scripting/scripting_world_generation.cpp | 3 +-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/logic/scripting/lua/lua_commons.hpp b/src/logic/scripting/lua/lua_commons.hpp index d0b99f67..ff94ade7 100644 --- a/src/logic/scripting/lua/lua_commons.hpp +++ b/src/logic/scripting/lua/lua_commons.hpp @@ -24,9 +24,29 @@ namespace lua { luaerror(const std::string& message); }; - void log_error(const std::string& text); - using State = lua_State; using Number = lua_Number; using Integer = lua_Integer; + + /// @brief Automatically resets stack top element index to the initial state + /// (when stackguard was created). Prevents Lua stack leak on exception + /// occurred out of Lua execution time, when engine controls scripting. + /// + /// + /// stackguard allows to not place lua::pop(...) into 'catch' blocks. + class stackguard { + int top; + State* state; + public: + stackguard(State* state) : state(state) { + top = lua_gettop(state); + } + + ~stackguard() { + lua_settop(state, top); + } + }; + + void log_error(const std::string& text); + } diff --git a/src/logic/scripting/scripting_world_generation.cpp b/src/logic/scripting/scripting_world_generation.cpp index 712aaa13..a1abee83 100644 --- a/src/logic/scripting/scripting_world_generation.cpp +++ b/src/logic/scripting/scripting_world_generation.cpp @@ -101,7 +101,6 @@ static inline BlocksLayers load_layers( layers.push_back( load_layer(L, -1, lastLayersHeight, hasResizeableLayer)); } catch (const std::runtime_error& err) { - lua::pop(L, 2); throw std::runtime_error( fieldname+" #"+std::to_string(i)+": "+err.what()); } @@ -117,6 +116,7 @@ std::unique_ptr scripting::load_generator( ) { auto env = create_environment(); auto L = lua::get_main_thread(); + lua::stackguard _(L); lua::pop(L, load_script(*env, "generator", file)); @@ -139,7 +139,6 @@ std::unique_ptr scripting::load_generator( groundLayers = load_layers(L, "layers"); seaLayers = load_layers(L, "sea_layers"); } catch (const std::runtime_error& err) { - lua::pop(L); throw std::runtime_error(file.u8string()+": "+err.what()); } lua::pop(L);