diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-08-20 21:12:25 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-08-20 21:12:25 -0400 |
commit | 376c890c095fbc59b83402255cc1036c411150b9 (patch) | |
tree | 7c15346acb6121e5a3312ffe945f4a419f849307 /indra/newview | |
parent | 68313aa2defcc7d6e5ebbd96344d78f3a31fdb9a (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.cpp | 5 |
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); |