summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-08-20 21:12:25 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-08-20 21:12:25 -0400
commit376c890c095fbc59b83402255cc1036c411150b9 (patch)
tree7c15346acb6121e5a3312ffe945f4a419f849307 /indra/newview
parent68313aa2defcc7d6e5ebbd96344d78f3a31fdb9a (diff)
Fix for #2237: intermittent Lua data stack overflow.
Use a static unordered_map to allow a function receiving (lua_State* L) to look up the LuaState instance managing that lua_State. We've thought about this from time to time already. LuaState's constructor creates the map entry; its destructor removes it; the new static getParent(lua_State* L) method performs the lookup. Migrate lluau::set_interrupts_counter() and check_interrupts_counter() into LuaState member functions. Add a new mInterrupts counter for them. Importantly, LuaState::check_interrupts_counter(), which is indirectly called by a lua_callbacks().interrupt function, no longer performs any Lua stack operations. Empirically, it seems the Lua engine is capable of interrupting itself at a moment when re-entry confuses it. Change previous lluau::set_interrupts_counter(L, 0) calls to LuaState::getParent(L).set_interrupts_counter(0). Also add LuaStackDelta class, and a lua_checkdelta() helper macro, to verify that the Lua data stack depth on exit from a block differs from the depth on entry by exactly the expected amount. Sprinkle lua_checkdelta() macros in likely places.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llluamanager.cpp5
1 files changed, 5 insertions, 0 deletions
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp
index 0b1a73f4e9..6de8829308 100644
--- a/indra/newview/llluamanager.cpp
+++ b/indra/newview/llluamanager.cpp
@@ -53,6 +53,7 @@ std::map<std::string, std::string> LLLUAmanager::sScriptNames;
lua_function(sleep, "sleep(seconds): pause the running coroutine")
{
+ lua_checkdelta(L, -1);
F32 seconds = lua_tonumber(L, -1);
lua_pop(L, 1);
llcoro::suspendUntilTimeout(seconds);
@@ -125,6 +126,7 @@ lua_function(print_warning, "print_warning(args...): WARNING level logging")
lua_function(post_on, "post_on(pumpname, data): post specified data to specified LLEventPump")
{
+ lua_checkdelta(L, -2);
std::string pumpname{ lua_tostdstring(L, 1) };
LLSD data{ lua_tollsd(L, 2) };
lua_pop(L, 2);
@@ -139,6 +141,7 @@ lua_function(get_event_pumps,
"Events posted to replypump are queued for get_event_next().\n"
"post_on(commandpump, ...) to engage LLEventAPI operations (see helpleap()).")
{
+ lua_checkdelta(L, 2);
lluau_checkstack(L, 2);
auto& listener{ LuaState::obtainListener(L) };
// return the reply pump name and the command pump name on caller's lua_State
@@ -153,6 +156,7 @@ lua_function(get_event_next,
"is returned by get_event_pumps(). Blocks the calling chunk until an\n"
"event becomes available.")
{
+ lua_checkdelta(L, 2);
lluau_checkstack(L, 2);
auto& listener{ LuaState::obtainListener(L) };
const auto& [pump, data]{ listener.getNext() };
@@ -271,6 +275,7 @@ std::string read_file(const std::string &name)
lua_function(require, "require(module_name) : load module_name.lua from known places")
{
+ lua_checkdelta(L);
std::string name = lua_tostdstring(L, 1);
lua_pop(L, 1);