summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llfloaterluascripts.cpp3
-rw-r--r--indra/newview/llluamanager.cpp50
-rw-r--r--indra/newview/llluamanager.h3
-rw-r--r--indra/newview/tests/llluamanager_test.cpp35
4 files changed, 34 insertions, 57 deletions
diff --git a/indra/newview/llfloaterluascripts.cpp b/indra/newview/llfloaterluascripts.cpp
index 30353a7210..39d5816b0d 100644
--- a/indra/newview/llfloaterluascripts.cpp
+++ b/indra/newview/llfloaterluascripts.cpp
@@ -54,8 +54,7 @@ LLFloaterLUAScripts::LLFloaterLUAScripts(const LLSD &key)
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);
+ LLCoros::instance().killreq(coro_name);
}
});
}
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp
index dfa27ebc37..97779a12ad 100644
--- a/indra/newview/llluamanager.cpp
+++ b/indra/newview/llluamanager.cpp
@@ -49,24 +49,13 @@
#include <vector>
std::map<std::string, std::string> LLLUAmanager::sScriptNames;
-std::set<std::string> LLLUAmanager::sTerminationList;
-
-const S32 INTERRUPTS_MAX_LIMIT = 20000;
-const S32 INTERRUPTS_SUSPEND_LIMIT = 100;
-
-void set_interrupts_counter(lua_State *L, S32 counter)
-{
- lua_pushstring(L, "_INTERRUPTS");
- lua_pushinteger(L, counter);
- lua_rawset(L, LUA_REGISTRYINDEX);
-}
lua_function(sleep, "sleep(seconds): pause the running coroutine")
{
F32 seconds = lua_tonumber(L, -1);
lua_pop(L, 1);
llcoro::suspendUntilTimeout(seconds);
- set_interrupts_counter(L, 0);
+ lluau::set_interrupts_counter(L, 0);
return 0;
};
@@ -168,7 +157,7 @@ lua_function(get_event_next,
const auto& [pump, data]{ listener->getNext() };
lua_pushstdstring(L, pump);
lua_pushllsd(L, data);
- set_interrupts_counter(L, 0);
+ lluau::set_interrupts_counter(L, 0);
return 2;
}
@@ -189,25 +178,6 @@ std::pair<int, LLSD> LLLUAmanager::waitScriptFile(const std::string& filename)
return startScriptFile(filename).get();
}
-void check_interrupts_counter(lua_State* L)
-{
- lua_pushstring(L, "_INTERRUPTS");
- lua_rawget(L, LUA_REGISTRYINDEX);
- S32 counter = lua_tointeger(L, -1);
- lua_pop(L, 1);
-
- counter++;
- if (counter > INTERRUPTS_MAX_LIMIT)
- {
- lluau::error(L, "Possible infinite loop, terminated.");
- }
- else if (counter % INTERRUPTS_SUSPEND_LIMIT == 0)
- {
- llcoro::suspend();
- }
- set_interrupts_counter(L, counter);
-}
-
void LLLUAmanager::runScriptFile(const std::string &filename, script_result_fn result_cb, script_finished_fn finished_cb)
{
// A script_result_fn will be called when LuaState::expr() completes.
@@ -222,22 +192,6 @@ 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);
- set_interrupts_counter(L, 0);
-
- 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");
- }
- check_interrupts_counter(L);
- };
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 d671719bc4..af9dcf70c2 100644
--- a/indra/newview/llluamanager.h
+++ b/indra/newview/llluamanager.h
@@ -85,12 +85,9 @@ 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::set<std::string> sTerminationList;
};
class LLRequireResolver
diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp
index b907ac6619..cf1bf25b5c 100644
--- a/indra/newview/tests/llluamanager_test.cpp
+++ b/indra/newview/tests/llluamanager_test.cpp
@@ -400,9 +400,16 @@ namespace tut
auto future = LLLUAmanager::startScriptLine(L, lua);
auto replyname{ L.obtainListener()->getReplyName() };
auto& replypump{ LLEventPumps::instance().obtain(replyname) };
- // By the time leap.process() calls get_event_next() and wakes us up,
- // we expect that both requester() coroutines have posted and are
- // waiting for a reply.
+ // LuaState::expr() periodically interrupts a running chunk to ensure
+ // the rest of our coroutines get cycles. Nonetheless, for this test
+ // we have to wait until both requester() coroutines have posted and
+ // are waiting for a reply.
+ for (unsigned count=0; count < 100; ++count)
+ {
+ if (requests.size() == 2)
+ break;
+ llcoro::suspend();
+ }
ensure_equals("didn't get both requests", requests.size(), 2);
// moreover, we expect they arrived in the order they were created
ensure_equals("a wasn't first", requests[0]["name"].asString(), "a");
@@ -413,7 +420,7 @@ namespace tut
replypump.post(llsd::map("name", "not special"));
// now respond to requester(a)
replypump.post(requests[0]);
- // tell leap.process() we're done
+ // tell leap we're done
replypump.post(LLSD());
auto [count, result] = future.get();
ensure_equals("leap.lua: " + result.asString(), count, 0);
@@ -438,4 +445,24 @@ namespace tut
ensure_equals("unexpected killed Lua script error",
result.asString(), "viewer is stopping");
}
+
+ template<> template<>
+ void object::test<8>()
+ {
+ set_test_name("stop looping Lua script");
+ const std::string desc("looping Lua script should terminate");
+ const std::string lua(
+ "-- " + desc + "\n"
+ "\n"
+ "while true do\n"
+ " x = 1\n"
+ "end\n"
+ );
+ LuaState L;
+ auto [count, result] = LLLUAmanager::waitScriptLine(L, lua);
+ // We expect the above erroneous script has been forcibly terminated
+ // because it ran too long without doing any actual work.
+ ensure_equals(desc + " count: " + result.asString(), count, -1);
+ ensure_contains(desc + " result", result.asString(), "terminated");
+ }
} // namespace tut