summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-03-28 07:11:31 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-03-28 07:11:31 -0400
commitce73e5c5ab0c33673067d9322c98ae8800fa9224 (patch)
tree5efe142b37454a04bedea3319e455ea4c6a2a8e5 /indra/llcommon
parent9fbfd3d0ad1ed2cb721129a59421f06fedd071bf (diff)
Terminate Lua scripts hanging in LL.get_event_next().
Make LuaListener listen for "LLApp" viewer shutdown events. On receiving such, it closes its queue. Then the C++ coroutine calling getNext() wakes up with an LLThreadSafeQueue exception, and calls LLCoros::checkStop() to throw one of the exceptions recognized by LLCoros::toplevel(). Add an llluamanager_test.cpp test to verify this behavior.
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/lualistener.cpp31
-rw-r--r--indra/llcommon/lualistener.h2
2 files changed, 31 insertions, 2 deletions
diff --git a/indra/llcommon/lualistener.cpp b/indra/llcommon/lualistener.cpp
index ed34133924..37ce27a2a4 100644
--- a/indra/llcommon/lualistener.cpp
+++ b/indra/llcommon/lualistener.cpp
@@ -36,7 +36,24 @@ LuaListener::LuaListener(lua_State* L):
mListener(new LLLeapListener(
"LuaListener",
[this](const std::string& pump, const LLSD& data)
- { return queueEvent(pump, data); }))
+ { return queueEvent(pump, data); })),
+ // Listen for shutdown events on the "LLApp" LLEventPump.
+ mShutdownConnection(
+ LLEventPumps::instance().obtain("LLApp").listen(
+ LLEventPump::inventName("LuaState"),
+ [this](const LLSD& status)
+ {
+ LL_DEBUGS("LuaListener") << "caught " << status << LL_ENDL;
+ const auto& statsd = status["status"];
+ if (statsd.asString() != "running")
+ {
+ // If a Lua script is still blocked in getNext() during
+ // viewer shutdown, close the queue to wake up getNext().
+ LL_DEBUGS("LuaListener") << "closing queue" << LL_ENDL;
+ mQueue.close();
+ }
+ return false;
+ }))
{}
LuaListener::~LuaListener()
@@ -87,5 +104,15 @@ bool LuaListener::queueEvent(const std::string& pump, const LLSD& data)
LuaListener::PumpData LuaListener::getNext()
{
- return mQueue.pop();
+ try
+ {
+ return mQueue.pop();
+ }
+ catch (const LLThreadSafeQueueInterrupt& exc)
+ {
+ // mQueue has been closed. The only way that happens is when we detect
+ // viewer shutdown. Terminate the calling coroutine.
+ LLCoros::checkStop();
+ return {};
+ }
}
diff --git a/indra/llcommon/lualistener.h b/indra/llcommon/lualistener.h
index c13b7bbd5f..40ccfba8fe 100644
--- a/indra/llcommon/lualistener.h
+++ b/indra/llcommon/lualistener.h
@@ -12,6 +12,7 @@
#if ! defined(LL_LUALISTENER_H)
#define LL_LUALISTENER_H
+#include "llevents.h"
#include "llinstancetracker.h"
#include "llsd.h"
#include "llthreadsafequeue.h"
@@ -73,6 +74,7 @@ private:
LLThreadSafeQueue<PumpData> mQueue;
std::unique_ptr<LLLeapListener> mListener;
+ LLTempBoundListener mShutdownConnection;
};
#endif /* ! defined(LL_LUALISTENER_H) */