Skip to content

Commit b622868

Browse files
Merge pull request #3197 from secondlife/maxim/viewer-3119
#3119 crash when lua requests debug settings value
2 parents c420f04 + 9e6039e commit b622868

File tree

3 files changed

+53
-22
lines changed

3 files changed

+53
-22
lines changed

indra/llcommon/lua_function.cpp

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,34 @@ int lua_metaipair(lua_State* L)
764764

765765
} // anonymous namespace
766766

767+
int LuaState::push_debug_traceback()
768+
{
769+
// Push debug.traceback() onto the stack as lua_pcall()'s error
770+
// handler function. On error, lua_pcall() calls the specified error
771+
// handler function with the original error message; the message
772+
// returned by the error handler is then returned by lua_pcall().
773+
// Luau's debug.traceback() is called with a message to prepend to the
774+
// returned traceback string. Almost as if they'd been designed to
775+
// work together...
776+
lua_getglobal(mState, "debug");
777+
if (!lua_istable(mState, -1))
778+
{
779+
lua_pop(mState, 1);
780+
LL_WARNS("Lua") << "'debug' table not found" << LL_ENDL;
781+
return 0;
782+
}
783+
lua_getfield(mState, -1, "traceback");
784+
if (!lua_isfunction(mState, -1))
785+
{
786+
lua_pop(mState, 2);
787+
LL_WARNS("Lua") << "'traceback' func not found" << LL_ENDL;
788+
return 0;
789+
}
790+
// ditch "debug"
791+
lua_remove(mState, -2);
792+
return lua_gettop(mState);
793+
}
794+
767795
LuaState::~LuaState()
768796
{
769797
// If we're unwinding the stack due to an exception, don't bother trying
@@ -784,6 +812,8 @@ LuaState::~LuaState()
784812
// stack contains Registry.atexit
785813
if (lua_istable(mState, -1))
786814
{
815+
int atexit = lua_gettop(mState);
816+
787817
// We happen to know that Registry.atexit is built by appending array
788818
// entries using table.insert(). That's important because it means
789819
// there are no holes, and therefore lua_objlen() should be correct.
@@ -793,36 +823,25 @@ LuaState::~LuaState()
793823
LL_DEBUGS("Lua") << LLCoros::getName() << ": Registry.atexit is a table with "
794824
<< len << " entries" << LL_ENDL;
795825

796-
// Push debug.traceback() onto the stack as lua_pcall()'s error
797-
// handler function. On error, lua_pcall() calls the specified error
798-
// handler function with the original error message; the message
799-
// returned by the error handler is then returned by lua_pcall().
800-
// Luau's debug.traceback() is called with a message to prepend to the
801-
// returned traceback string. Almost as if they'd been designed to
802-
// work together...
803-
lua_getglobal(mState, "debug");
804-
lua_getfield(mState, -1, "traceback");
805-
// ditch "debug"
806-
lua_remove(mState, -2);
807-
// stack now contains atexit, debug.traceback()
808-
826+
// TODO: 'debug' global shouldn't be overwritten and should be accessible at this stage
827+
S32 debug_traceback_idx = push_debug_traceback();
828+
// if debug_traceback is true, stack now contains atexit, /debug.traceback()/
829+
// otherwise just atexit
809830
for (int i(len); i >= 1; --i)
810831
{
811832
lua_pushinteger(mState, i);
812-
// stack contains Registry.atexit, debug.traceback(), i
813-
lua_gettable(mState, -3);
814-
// stack contains Registry.atexit, debug.traceback(), atexit[i]
833+
// stack contains Registry.atexit, /debug.traceback()/, i
834+
lua_gettable(mState, atexit);
835+
// stack contains Registry.atexit, /debug.traceback()/, atexit[i]
815836
// Call atexit[i](), no args, no return values.
816837
// Use lua_pcall() because errors in any one atexit() function
817838
// shouldn't cancel the rest of them. Pass debug.traceback() as
818839
// the error handler function.
819-
LL_DEBUGS("Lua") << LLCoros::getName()
820-
<< ": calling atexit(" << i << ")" << LL_ENDL;
821-
if (lua_pcall(mState, 0, 0, -2) != LUA_OK)
840+
LL_DEBUGS("Lua") << LLCoros::getName() << ": calling atexit(" << i << ")" << LL_ENDL;
841+
if (lua_pcall(mState, 0, 0, debug_traceback_idx) != LUA_OK)
822842
{
823843
auto error{ lua_tostdstring(mState, -1) };
824-
LL_WARNS("Lua") << LLCoros::getName()
825-
<< ": atexit(" << i << ") error: " << error << LL_ENDL;
844+
LL_WARNS("Lua") << LLCoros::getName() << ": atexit(" << i << ") error: " << error << LL_ENDL;
826845
// pop error message
827846
lua_pop(mState, 1);
828847
}
@@ -831,7 +850,8 @@ LuaState::~LuaState()
831850
// stack contains atexit, debug.traceback()
832851
}
833852
// pop debug.traceback()
834-
lua_pop(mState, 1);
853+
if (debug_traceback_idx)
854+
lua_remove(mState, debug_traceback_idx);
835855
}
836856
// pop Registry.atexit (either table or nil)
837857
lua_pop(mState, 1);

indra/llcommon/lua_function.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class LuaState
122122
void set_interrupts_counter(S32 counter);
123123
void check_interrupts_counter();
124124

125+
int push_debug_traceback();
126+
125127
private:
126128
/*---------------------------- feature flag ----------------------------*/
127129
bool mFeature{ false };
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
local LLDebugSettings = require 'LLDebugSettings'
2+
local SETTING_NAME = '360CaptureCameraFOV'
3+
LL.atexit(function() LL.print_info('Finished') end)
4+
5+
LL.print_info('Updating ' .. SETTING_NAME)
6+
LLDebugSettings.set(SETTING_NAME, 100)
7+
-- 'inadvertently' using Luau library as variable name to hide it
8+
debug = LLDebugSettings.get(SETTING_NAME)
9+
LL.print_info(debug)

0 commit comments

Comments
 (0)