4

我正在试验一种游戏机制,其中玩家可以在游戏计算机上运行脚本。脚本执行将在游戏级别受到资源限制,每次滴答需要一定数量的指令。

以下概念验证演示了沙盒和任意用户代码节流的基本级别。它成功运行了约 250 条精心设计的“用户输入”指令,然后丢弃了协程。不幸的是,Java 进程永远不会终止。一点调查表明,LuaThread由 LuaJ 为协程创建的代码永远存在。

沙盒测试.java:

public static void main(String[] args) {
    Globals globals = JsePlatform.debugGlobals();

    LuaValue chunk = globals.loadfile("res/test.lua");

    chunk.call();
}

水库/test.lua:

function sandbox(fn)
    -- read script and set the environment
    f = loadfile(fn, "t")
    debug.setupvalue(f, 1, {print = print})

    -- create a coroutine and have it yield every 50 instructions
    local co = coroutine.create(f)
    debug.sethook(co, coroutine.yield, "", 50)

    -- demonstrate stepped execution, 5 'ticks'
    for i = 1, 5 do
        print("tick")
        coroutine.resume(co)
    end
end

sandbox("res/badfile.lua")

资源/坏文件.lua:

while 1 do
    print("", "badfile")
end

文档表明,被认为不可恢复的协程将被垃圾收集并OrphanedThread抛出异常,发出LuaThread结束信号——但这永远不会发生。我的问题分为两部分:

  • 我是否在做一些根本错误的事情来导致这种行为?
  • 如果没有,我应该如何处理这种情况?从源头看来,如果我能获得对LuaThreadJava 的引用,我可能可以通过发出interrupt(). 这是一个好主意吗?

参考:Lua / Java / LuaJ - 处理或中断无限循环和线程

编辑:我在 LuaJ SourceForge 上发布了一个错误报告。它讨论了潜在的问题(线程没有像 Lua 规范中那样被垃圾收集)并提出了一些解决方法。

4

1 回答 1

3

这似乎是 LuaJ 的限制。我今年早些时候在 Sourceforge 上提交了一张票,因为我看到你也这样做了。该类LuaThread不存储对它创建的 Java 线程的引用,因此如果interrupt()不修改 LuaJ 核心以公开它们,就不能使用这些线程:

new Thread(this, "Coroutine-"+(++coroutine_count)).start();

在没有向 LuaJ 添加适当的清理代码的情况下中断这些线程可能很危险。


您提供的文档OrphanedThread还告诉我们范围是定义条件:

“已检测到指示不再引用的 lua 线程的错误子类。抛出此错误的 java 线程应对应于被用作协程的 LuaThread,该协程不可能再次恢复,因为不再引用与其关联的 LuaThread。不是永远锁定资源,而是抛出此错误,并且应该一直传递到线程的 Thread.run() 方法。

您的代码示例不会导致所有 LuaThread 引用消失,因此您不应期望抛出异常。CoroutineLib文档表明:Coroutines that are yielded but never resumed to complete their execution may not be collected by the garbage collector,如果我没记错的话,OutOfMemoryError实际上应该从您在SourceForge上列出的代码中得到一个。LuaThread:52还指定:Applications should not catch OrphanedThread, because it can break the thread safety of luaj.,这是另一个障碍。


whileLua/J 中的空循环和非空循环之间似乎也存在差异。IIRC,空循环(while true do end)不遵守所有协程钩/勾规则。*因为在空循环中没有任何动作发生,所以某些钩子没有机会发生(我需要再次测试,否则请更正我!)。

具有我们正在寻找的功能的 LuaJ 的分叉版本用于 Minecraft 的 ComputerCraft mod,尽管它仅为该 mod 而设计并且不是开源的。

于 2014-07-07T19:17:53.783 回答