Improve collection of orphaned coroutines when yielding from debug hook functions.
This commit is contained in:
@@ -63,10 +63,14 @@ public class LuaThread extends LuaValue {
|
||||
|
||||
public static int coroutine_count = 0;
|
||||
|
||||
/** Interval at which to check for lua threads that are no longer referenced.
|
||||
* This can be changed by Java startup code if desired.
|
||||
/** Polling interval, in milliseconds, which each thread uses while waiting to
|
||||
* return from a yielded state to check if the lua threads is no longer
|
||||
* referenced and therefore should be garbage collected.
|
||||
* A short polling interval for many threads will consume server resources.
|
||||
* Orphaned threads cannot be detected and collected unless garbage
|
||||
* collection is run. This can be changed by Java startup code if desired.
|
||||
*/
|
||||
static long thread_orphan_check_interval = 30000;
|
||||
public static long thread_orphan_check_interval = 5000;
|
||||
|
||||
public static final int STATUS_INITIAL = 0;
|
||||
public static final int STATUS_SUSPENDED = 1;
|
||||
@@ -83,12 +87,9 @@ public class LuaThread extends LuaValue {
|
||||
public final State state;
|
||||
|
||||
public static final int MAX_CALLSTACK = 256;
|
||||
|
||||
/** Interval to check for LuaThread dereferencing. */
|
||||
public static int GC_INTERVAL = 30000;
|
||||
|
||||
/** Thread-local used by DebugLib to store debugging state.
|
||||
* This is ano opaque value that should not be modified by applications. */
|
||||
* This is an opaque value that should not be modified by applications. */
|
||||
public Object callstack;
|
||||
|
||||
public final Globals globals;
|
||||
@@ -244,6 +245,15 @@ public class LuaThread extends LuaValue {
|
||||
this.result = LuaValue.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void set_inhook(boolean value) {
|
||||
LuaThread t = (LuaThread) this.lua_thread.get();
|
||||
if (t == null) {
|
||||
this.status = STATUS_DEAD;
|
||||
throw new OrphanedThread();
|
||||
}
|
||||
t.inhook = value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,8 +62,6 @@ import org.luaj.vm2.Varargs;
|
||||
*/
|
||||
public class CoroutineLib extends TwoArgFunction {
|
||||
|
||||
static long thread_orphan_check_interval = 30000;
|
||||
|
||||
static int coroutine_count = 0;
|
||||
|
||||
Globals globals;
|
||||
|
||||
@@ -388,61 +388,55 @@ public class DebugLib extends TwoArgFunction {
|
||||
}
|
||||
|
||||
public void onCall(LuaFunction f) {
|
||||
LuaThread t = globals.running;
|
||||
if (t.inhook) return;
|
||||
if (globals.running.inhook) return;
|
||||
callstack().onCall(f);
|
||||
if (t.hookcall && t.hookfunc != null)
|
||||
callHook(CALL, NIL);
|
||||
callHook(globals.running.hookfunc, CALL, NIL);
|
||||
}
|
||||
|
||||
public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) {
|
||||
LuaThread t = globals.running;
|
||||
if (t.inhook) return;
|
||||
if (globals.running.inhook) return;
|
||||
callstack().onCall(c, varargs, stack);
|
||||
if (t.hookcall && t.hookfunc != null)
|
||||
callHook(CALL, NIL);
|
||||
callHook(globals.running.hookfunc, CALL, NIL);
|
||||
}
|
||||
|
||||
public void onInstruction(int pc, Varargs v, int top) {
|
||||
LuaThread t = globals.running;
|
||||
if (t.inhook) return;
|
||||
if (globals.running.inhook) return;
|
||||
callstack().onInstruction(pc, v, top);
|
||||
if (t.hookfunc == null) return;
|
||||
if (t.hookcount > 0)
|
||||
if (++t.bytecodes % t.hookcount == 0)
|
||||
callHook(COUNT, NIL);
|
||||
if (t.hookline) {
|
||||
if (globals.running.hookfunc == null) return;
|
||||
if (globals.running.hookcount > 0)
|
||||
if (++globals.running.bytecodes % globals.running.hookcount == 0)
|
||||
callHook(globals.running.hookfunc, COUNT, NIL);
|
||||
if (globals.running.hookline) {
|
||||
int newline = callstack().currentline();
|
||||
if ( newline != t.lastline ) {
|
||||
t.lastline = newline;
|
||||
callHook(LINE, LuaValue.valueOf(newline));
|
||||
if ( newline != globals.running.lastline ) {
|
||||
globals.running.lastline = newline;
|
||||
callHook(globals.running.hookfunc, LINE, LuaValue.valueOf(newline));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onReturn() {
|
||||
LuaThread t = globals.running;
|
||||
if (t.inhook) return;
|
||||
if (globals.running.inhook) return;
|
||||
callstack().onReturn();
|
||||
if (t.hookcall && t.hookfunc != null)
|
||||
callHook(RETURN, NIL);
|
||||
callHook(globals.running.hookfunc, RETURN, NIL);
|
||||
}
|
||||
|
||||
public String traceback(int level) {
|
||||
return callstack().traceback(level);
|
||||
}
|
||||
|
||||
void callHook(LuaValue type, LuaValue arg) {
|
||||
LuaThread t = globals.running;
|
||||
t.inhook = true;
|
||||
void callHook(LuaValue hookfunc, LuaValue type, LuaValue arg) {
|
||||
if (hookfunc == null) return;
|
||||
LuaThread.State state = globals.running.state;
|
||||
state.set_inhook(true);
|
||||
try {
|
||||
t.hookfunc.call(type, arg);
|
||||
hookfunc.call(type, arg);
|
||||
} catch (LuaError e) {
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
throw new LuaError(e);
|
||||
} finally {
|
||||
t.inhook = false;
|
||||
state.set_inhook(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user