diff --git a/core/src/main/java/org/luaj/vm2/LuaClosure.class b/core/src/main/java/org/luaj/vm2/LuaClosure.class index 1b485a2f..83fa4ec3 100644 Binary files a/core/src/main/java/org/luaj/vm2/LuaClosure.class and b/core/src/main/java/org/luaj/vm2/LuaClosure.class differ diff --git a/core/src/main/java/org/luaj/vm2/LuaClosure.java b/core/src/main/java/org/luaj/vm2/LuaClosure.java index 25e9d60e..735c7a66 100644 --- a/core/src/main/java/org/luaj/vm2/LuaClosure.java +++ b/core/src/main/java/org/luaj/vm2/LuaClosure.java @@ -259,6 +259,9 @@ public class LuaClosure extends LuaFunction { // process instructions try { for (; true; ++pc) { + if (Thread.currentThread().isInterrupted()) { + throw new LuaError("interrupted"); + } if (globals != null && globals.debuglib != null) globals.debuglib.onInstruction( pc, v, top ); diff --git a/jse/src/test/java/org/luaj/vm2/FragmentsTest.java b/jse/src/test/java/org/luaj/vm2/FragmentsTest.java index 50db64fd..00362cb6 100644 --- a/jse/src/test/java/org/luaj/vm2/FragmentsTest.java +++ b/jse/src/test/java/org/luaj/vm2/FragmentsTest.java @@ -23,6 +23,7 @@ package org.luaj.vm2; import java.io.Reader; import java.io.StringReader; +import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; import junit.framework.TestSuite; @@ -162,6 +163,32 @@ public class FragmentsTest extends TestSuite { "return ok\n"); } + public void testInterruptedThreadStopsRunningClosure() throws Exception { + final Globals globals = JsePlatform.debugGlobals(); + final LuaValue chunk = globals.load("while true do end", "interrupt.lua"); + final AtomicReference thrown = new AtomicReference(); + + Thread t = new Thread(new Runnable() { + public void run() { + try { + chunk.call(); + } catch (Throwable e) { + thrown.set(e); + } + } + }, "luaj-interrupt-test"); + t.start(); + + Thread.sleep(50); + t.interrupt(); + t.join(2000); + + assertFalse("lua thread should stop after interrupt", t.isAlive()); + assertNotNull("expected LuaError from interrupt", thrown.get()); + assertEquals(LuaError.class, thrown.get().getClass()); + assertEquals("interrupted", thrown.get().getMessage()); + } + public void testLongIntegerLiteralPrecision() { runFragment( LuaValue.varargsOf(new LuaValue[] {