Posted 05 July 2013 - 04:43 PM
Title: Lua / Java - Handling or Interrupting Infinite Loops and Threads - debug.sethook?
I'm using the LuaJ library to develop an application that will call user-created Lua scripts from Java. I currently call each Lua script in its own Java thread so multiple scripts can run simultaneously. However, Lua scripts which contain infinite loops such as "while true do end" cause the calling thread to freeze and make it impossible (it seems) to interrupt() the thread. The same goes for Java threads which run: while (true);. They are seemingly uninterruptible.
ComputerCraft detects these kinds of infinite loops and also allows users to terminate their scripts while they are running (CTRL+T). I looked at ComputerCraft's source code (I hope that's ok…) in hopes of discovering how it was done, but it was too dense for me to make much sense of it. I did find some telling lines, but I was wondering if anyone could provide some clarification for me. I found some information on debug.sethook, but I can't figure out how to properly use it, if it's appropriate at all. I've attached relevant code below from CC. Please let me know immediately if these code snippets shouldn't be here.
/src/dan200/computer/core/LuaJLuaMachine$1.java:
This line in the above LuaJLuaMachine$1.java is very encouraging:
/src/dan200/computer/core/Computer.java, line 123:
There's also a massive section of code in ComputerThread$1.java which seems to at one point call the above abort() function. It's far too long to post here but it exists:
/src/dan200/computer/core/ComputerThread$1.java, line 95:
If anyone has any information regarding interrupting "uninterruptible" Java threads, or using debug.sethook or other Lua features to halt Lua programs while they are running, please share! Thank you.
I'm using the LuaJ library to develop an application that will call user-created Lua scripts from Java. I currently call each Lua script in its own Java thread so multiple scripts can run simultaneously. However, Lua scripts which contain infinite loops such as "while true do end" cause the calling thread to freeze and make it impossible (it seems) to interrupt() the thread. The same goes for Java threads which run: while (true);. They are seemingly uninterruptible.
ComputerCraft detects these kinds of infinite loops and also allows users to terminate their scripts while they are running (CTRL+T). I looked at ComputerCraft's source code (I hope that's ok…) in hopes of discovering how it was done, but it was too dense for me to make much sense of it. I did find some telling lines, but I was wondering if anyone could provide some clarification for me. I found some information on debug.sethook, but I can't figure out how to properly use it, if it's appropriate at all. I've attached relevant code below from CC. Please let me know immediately if these code snippets shouldn't be here.
Spoiler
/src/dan200/computer/core/LuaJLuaMachine.java, line 42 in constructor:Spoiler
LuaValue var1 = this.m_globals.get("coroutine");
LuaValue var2 = var1.get("create");
LuaValue var3 = this.m_globals.get("debug");
LuaValue var4 = var3.get("sethook");
var1.set("create", (LuaValue)(new LuaJLuaMachine$1(this, var2, var4)));
/src/dan200/computer/core/LuaJLuaMachine$1.java:
Spoiler
package dan200.computer.core;
import dan200.computer.core.LuaJLuaMachine$1$1;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.OneArgFunction;
class LuaJLuaMachine$1 extends OneArgFunction
{
final LuaValue val$native_coroutine_create;
final LuaValue val$debug_sethook;
final LuaJLuaMachine this$0;
LuaJLuaMachine$1(LuaJLuaMachine var1, LuaValue var2, LuaValue var3)
{
this.this$0 = var1;
this.val$native_coroutine_create = var2;
this.val$debug_sethook = var3;
}
public LuaValue call(LuaValue var1)
{
LuaThread var2 = this.val$native_coroutine_create.call(var1).checkthread();
this.val$debug_sethook.invoke(new LuaValue[] {var2, new LuaJLuaMachine$1$1(this, var2), LuaValue.NIL, LuaValue.valueOf(100000)});
return var2;
}
}
This line in the above LuaJLuaMachine$1.java is very encouraging:
this.val$debug_sethook.invoke(new LuaValue[] {var2, new LuaJLuaMachine$1$1(this, var2), LuaValue.NIL, LuaValue.valueOf(100000)});
/src/dan200/computer/core/Computer.java, line 123:
Spoiler
public void abort(boolean var1)
{
synchronized (this)
{
if (this.m_state == 2)
{
if (var1)
{
this.m_machine.hardAbort("Too long without yielding");
}
else
{
this.m_machine.softAbort("Too long without yielding");
}
}
}
}
There's also a massive section of code in ComputerThread$1.java which seems to at one point call the above abort() function. It's far too long to post here but it exists:
/src/dan200/computer/core/ComputerThread$1.java, line 95:
var5.abort(false);
If anyone has any information regarding interrupting "uninterruptible" Java threads, or using debug.sethook or other Lua features to halt Lua programs while they are running, please share! Thank you.