summaryrefslogtreecommitdiff
path: root/indra/llcommon/lua_function.cpp
diff options
context:
space:
mode:
authornat-goodspeed <nat@lindenlab.com>2024-03-15 14:56:43 -0400
committerGitHub <noreply@github.com>2024-03-15 14:56:43 -0400
commitc5dec705cf6bb3dce9381c9ec574335356051297 (patch)
tree0620f4bab572b1cd38ba8e8db03130b1e65ec1f7 /indra/llcommon/lua_function.cpp
parentee8bc528bbf97ee8cc488651fb263b07b5c1c818 (diff)
parentbac113e30d987d7884c58490e6ea39a1bbd87d05 (diff)
Merge pull request #1004 from secondlife/lua-leap
Add leap.lua module to mediate LEAP request/response viewer interactions.
Diffstat (limited to 'indra/llcommon/lua_function.cpp')
-rw-r--r--indra/llcommon/lua_function.cpp38
1 files changed, 35 insertions, 3 deletions
diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp
index 78abb8ba7e..b5de5099ba 100644
--- a/indra/llcommon/lua_function.cpp
+++ b/indra/llcommon/lua_function.cpp
@@ -16,9 +16,11 @@
// STL headers
// std headers
#include <algorithm>
+#include <exception>
#include <iomanip> // std::quoted
#include <map>
#include <memory> // std::unique_ptr
+#include <typeinfo>
// external library headers
// other Linden headers
#include "hexdump.h"
@@ -26,6 +28,7 @@
#include "llsd.h"
#include "llsdutil.h"
#include "lualistener.h"
+#include "stringize.h"
/*****************************************************************************
* luau namespace
@@ -496,16 +499,45 @@ std::pair<int, LLSD> LuaState::expr(const std::string& desc, const std::string&
// aha, at least one entry on the stack!
if (result.first == 1)
{
- result.second = lua_tollsd(mState, 1);
+ // Don't forget that lua_tollsd() can throw Lua errors.
+ try
+ {
+ result.second = lua_tollsd(mState, 1);
+ }
+ catch (const std::exception& error)
+ {
+ // lua_tollsd() is designed to be called from a lua_function(),
+ // that is, from a C++ function called by Lua. In case of error,
+ // it throws a Lua error to be caught by the Lua runtime. expr()
+ // is a peculiar use case in which our C++ code is calling
+ // lua_tollsd() after return from the Lua runtime. We must catch
+ // the exception thrown for a Lua error, else it will propagate
+ // out to the main coroutine and terminate the viewer -- but since
+ // we instead of the Lua runtime catch it, our lua_State retains
+ // its internal error status. Any subsequent lua_pcall() calls
+ // with this lua_State will report error regardless of whether the
+ // chunk runs successfully. Get a new lua_State().
+ initLuaState();
+ return { -1, stringize(LLError::Log::classname(error), ": ", error.what()) };
+ }
// pop the result we claimed
lua_settop(mState, 0);
return result;
}
// multiple entries on the stack
- for (int index = 1; index <= result.first; ++index)
+ try
+ {
+ for (int index = 1; index <= result.first; ++index)
+ {
+ result.second.append(lua_tollsd(mState, index));
+ }
+ }
+ catch (const std::exception& error)
{
- result.second.append(lua_tollsd(mState, index));
+ // see above comments regarding lua_State's error status
+ initLuaState();
+ return { -1, stringize(LLError::Log::classname(error), ": ", error.what()) };
}
// pop everything
lua_settop(mState, 0);