diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-03-28 07:11:31 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-03-28 07:11:31 -0400 |
commit | ce73e5c5ab0c33673067d9322c98ae8800fa9224 (patch) | |
tree | 5efe142b37454a04bedea3319e455ea4c6a2a8e5 /indra/llcommon | |
parent | 9fbfd3d0ad1ed2cb721129a59421f06fedd071bf (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.cpp | 31 | ||||
-rw-r--r-- | indra/llcommon/lualistener.h | 2 |
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) */ |