4

私は、プレイヤーがゲーム内のコンピューターでスクリプトを実行できるゲーム メカニクスを試しています。スクリプトの実行は、ゲームプレイ レベルで 1 ティックあたりの命令数にリソースが制限されます。

次の概念実証は、任意のユーザー コードのサンドボックス化とスロットリングの基本レベルを示しています。巧妙に作成されていない「ユーザー入力」の約 250 命令を正常に実行し、コルーチンを破棄します。残念ながら、Java プロセスは決して終了しません。少し調べてLuaThreadみると、コルーチン用に LuaJ によって作成された が永遠にぶら下がっていることがわかります。

SandboxTest.java:

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

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

    chunk.call();
}

res/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")

res/badfile.lua:

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

ドキュメントは、再開不可能と見なされるコルーチンがガベージ コレクションされ、OrphanedThread例外がスローされ、LuaThread終了することを通知することを示唆していますが、これは決して起こりません。私の質問は2つの部分に分かれています:

  • この動作を引き起こすために根本的に間違ったことをしていますか?
  • そうでない場合、この状況にどのように対処すればよいですか? LuaThreadソースからは、Java でへの参照を取得できれば、 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 スレッドを示すエラー sublcass が検出されました。これがスローされた Java スレッドは、LuaThreadへの参照がなくなったため、再び再開できなかった可能性があるコルーチンとして使用されていることに対応する必要があります。リソースを永久にロックするのではなく、このエラーがスローされ、スレッドの Thread.run() メソッドまでずっとフォールスルーする必要があります。

あなたのコード例では、すべての LuaThread 参照が消えるわけではないため、例外がスローされるとは思わないでください。CoroutineLibドキュメントには次Coroutines that are yielded but never resumed to complete their execution may not be collected by the garbage collectorのように示されています。したがって、私が間違っていなければ、 SourceForge にリストしたコードからOutOfMemoryError実際に期待されるはずです。も指定します: 、これはさらに別の障害です。LuaThread:52Applications 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 に答える