summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornat-goodspeed <nat@lindenlab.com>2024-04-12 16:40:41 -0400
committerGitHub <noreply@github.com>2024-04-12 16:40:41 -0400
commit3a1a3bb9248939bfec431dc10814eb598591f78a (patch)
tree779f80cf4a91db7a43622a9a6d50edc66ce125a8
parent7f9723bd5e05ea5318a56466578467f2755a6f4b (diff)
parent396ae60e1528515d0cbdfc4290b24ccb172998c8 (diff)
Merge pull request #1152 from secondlife/lua-terminate-script
Add script termination option to 'Lua Scripts' floater
-rw-r--r--indra/llcommon/llapp.cpp1
-rw-r--r--indra/llcommon/lualistener.cpp8
-rw-r--r--indra/llcommon/lualistener.h2
-rw-r--r--indra/newview/llfloaterluascripts.cpp16
-rw-r--r--indra/newview/llfloaterluascripts.h1
-rw-r--r--indra/newview/llluamanager.cpp15
-rw-r--r--indra/newview/llluamanager.h5
-rw-r--r--indra/newview/skins/default/xui/en/menu_lua_scripts.xml8
8 files changed, 49 insertions, 7 deletions
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index b99166991f..905db9e491 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -429,6 +429,7 @@ void LLApp::setStatus(EAppStatus status)
statsd = LLSD::Integer(status);
}
LLEventPumps::instance().obtain("LLApp").post(llsd::map("status", statsd));
+ LLEventPumps::instance().obtain("LLLua").post(llsd::map("status", "close_all"));
}
}
diff --git a/indra/llcommon/lualistener.cpp b/indra/llcommon/lualistener.cpp
index 82e32860db..d4bd73a9fb 100644
--- a/indra/llcommon/lualistener.cpp
+++ b/indra/llcommon/lualistener.cpp
@@ -33,18 +33,20 @@ std::ostream& operator<<(std::ostream& out, const LuaListener& self)
LuaListener::LuaListener(lua_State* L):
super(getUniqueKey()),
+ mCoroName(LLCoros::getName()),
mListener(new LLLeapListener(
"LuaListener",
[this](const std::string& pump, const LLSD& data)
{ return queueEvent(pump, data); })),
// Listen for shutdown events on the "LLApp" LLEventPump.
mShutdownConnection(
- LLEventPumps::instance().obtain("LLApp").listen(
+ LLEventPumps::instance().obtain("LLLua").listen(
LLEventPump::inventName("LuaState"),
[this](const LLSD& status)
{
- const auto& statsd = status["status"];
- if (statsd.asString() != "running")
+ auto coro_name = status["coro"].asString();
+ auto statsd = status["status"].asString();
+ if ((statsd == "close_all") || ((statsd == "close") && (coro_name == mCoroName)))
{
// If a Lua script is still blocked in getNext() during
// viewer shutdown, close the queue to wake up getNext().
diff --git a/indra/llcommon/lualistener.h b/indra/llcommon/lualistener.h
index 40ccfba8fe..d349ee23fd 100644
--- a/indra/llcommon/lualistener.h
+++ b/indra/llcommon/lualistener.h
@@ -75,6 +75,8 @@ private:
std::unique_ptr<LLLeapListener> mListener;
LLTempBoundListener mShutdownConnection;
+
+ std::string mCoroName;
};
#endif /* ! defined(LL_LUALISTENER_H) */
diff --git a/indra/newview/llfloaterluascripts.cpp b/indra/newview/llfloaterluascripts.cpp
index bd845a97d6..30353a7210 100644
--- a/indra/newview/llfloaterluascripts.cpp
+++ b/indra/newview/llfloaterluascripts.cpp
@@ -43,7 +43,20 @@ LLFloaterLUAScripts::LLFloaterLUAScripts(const LLSD &key)
{
mCommitCallbackRegistrar.add("Script.OpenFolder", [this](LLUICtrl*, const LLSD &userdata)
{
- gViewerWindow->getWindow()->openFolder(mTargetFolderPath);
+ if (mScriptList->hasSelectedItem())
+ {
+ std::string target_folder_path = std::filesystem::path((mScriptList->getFirstSelected()->getColumn(1)->getValue().asString())).parent_path().string();
+ gViewerWindow->getWindow()->openFolder(target_folder_path);
+ }
+ });
+ mCommitCallbackRegistrar.add("Script.Terminate", [this](LLUICtrl*, const LLSD &userdata)
+ {
+ if (mScriptList->hasSelectedItem())
+ {
+ std::string coro_name = mScriptList->getSelectedValue();
+ LLEventPumps::instance().obtain("LLLua").post(llsd::map("status", "close", "coro", coro_name));
+ LLLUAmanager::terminateScript(coro_name);
+ }
});
}
@@ -112,7 +125,6 @@ void LLFloaterLUAScripts::onScrollListRightClicked(LLUICtrl *ctrl, S32 x, S32 y)
auto menu = mContextMenuHandle.get();
if (menu)
{
- mTargetFolderPath = std::filesystem::path((item->getColumn(1)->getValue().asString())).parent_path().string();
menu->show(x, y);
LLMenuGL::showPopup(this, menu, x, y);
}
diff --git a/indra/newview/llfloaterluascripts.h b/indra/newview/llfloaterluascripts.h
index 548bbd10f6..932c5c78dd 100644
--- a/indra/newview/llfloaterluascripts.h
+++ b/indra/newview/llfloaterluascripts.h
@@ -46,7 +46,6 @@ private:
std::unique_ptr<LLTimer> mUpdateTimer;
LLScrollListCtrl* mScriptList;
- std::string mTargetFolderPath;
LLHandle<LLContextMenu> mContextMenuHandle;
};
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp
index 1d55313813..853ed5a634 100644
--- a/indra/newview/llluamanager.cpp
+++ b/indra/newview/llluamanager.cpp
@@ -49,6 +49,7 @@
#include <vector>
std::map<std::string, std::string> LLLUAmanager::sScriptNames;
+std::set<std::string> LLLUAmanager::sTerminationList;
lua_function(sleep, "sleep(seconds): pause the running coroutine")
{
@@ -188,6 +189,20 @@ void LLLUAmanager::runScriptFile(const std::string &filename, script_result_fn r
// A script_finished_fn is used to initialize the LuaState.
// It will be called when the LuaState is destroyed.
LuaState L(finished_cb);
+
+ lua_callbacks(L)->interrupt = [](lua_State *L, int gc)
+ {
+ // skip if we're interrupting only for garbage collection
+ if (gc >= 0)
+ return;
+
+ auto it = sTerminationList.find(LLCoros::getName());
+ if (it != sTerminationList.end())
+ {
+ sTerminationList.erase(it);
+ lluau::error(L, "Script was terminated");
+ }
+ };
std::string text{std::istreambuf_iterator<char>(in_file), {}};
auto [count, result] = L.expr(filename, text);
if (result_cb)
diff --git a/indra/newview/llluamanager.h b/indra/newview/llluamanager.h
index fe4db22fca..d671719bc4 100644
--- a/indra/newview/llluamanager.h
+++ b/indra/newview/llluamanager.h
@@ -85,9 +85,12 @@ public:
static void runScriptOnLogin();
static const std::map<std::string, std::string> getScriptNames() { return sScriptNames; }
+ static std::set<std::string> getTerminationList() { return sTerminationList; }
+ static void terminateScript(std::string& coro_name) { sTerminationList.insert(coro_name); }
private:
- static std::map<std::string, std::string> sScriptNames;
+ static std::map<std::string, std::string> sScriptNames;
+ static std::set<std::string> sTerminationList;
};
class LLRequireResolver
diff --git a/indra/newview/skins/default/xui/en/menu_lua_scripts.xml b/indra/newview/skins/default/xui/en/menu_lua_scripts.xml
index 8f718abe17..645fee405d 100644
--- a/indra/newview/skins/default/xui/en/menu_lua_scripts.xml
+++ b/indra/newview/skins/default/xui/en/menu_lua_scripts.xml
@@ -8,4 +8,12 @@
<menu_item_call.on_click
function="Script.OpenFolder" />
</menu_item_call>
+ <menu_item_separator/>
+ <menu_item_call
+ label="Terminate script"
+ layout="topleft"
+ name="terminate">
+ <menu_item_call.on_click
+ function="Script.Terminate" />
+ </menu_item_call>
</context_menu>