Improve collection of orphaned coroutines when yielding from debug hook functions.
This commit is contained in:
@@ -977,6 +977,7 @@ Files are no longer hosted at LuaForge.
|
|||||||
<li>Fix return value for table.remove() and table.insert() (fixes issue #39)</li>
|
<li>Fix return value for table.remove() and table.insert() (fixes issue #39)</li>
|
||||||
<li>Fix aliasing issue for some multiple assignments from varargs return values (fixes issue #38)</li>
|
<li>Fix aliasing issue for some multiple assignments from varargs return values (fixes issue #38)</li>
|
||||||
<li>Let os.getenv() return System.getenv() values first for JSE, then fall back to properties (fixes issue #25)</li>
|
<li>Let os.getenv() return System.getenv() values first for JSE, then fall back to properties (fixes issue #25)</li>
|
||||||
|
<li>Improve collection of orphaned coroutines when yielding from debug hook functions.</li>
|
||||||
|
|
||||||
</ul></td></tr>
|
</ul></td></tr>
|
||||||
</table></td></tr></table>
|
</table></td></tr></table>
|
||||||
|
|||||||
@@ -63,10 +63,14 @@ public class LuaThread extends LuaValue {
|
|||||||
|
|
||||||
public static int coroutine_count = 0;
|
public static int coroutine_count = 0;
|
||||||
|
|
||||||
/** Interval at which to check for lua threads that are no longer referenced.
|
/** Polling interval, in milliseconds, which each thread uses while waiting to
|
||||||
* This can be changed by Java startup code if desired.
|
* 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_INITIAL = 0;
|
||||||
public static final int STATUS_SUSPENDED = 1;
|
public static final int STATUS_SUSPENDED = 1;
|
||||||
@@ -83,12 +87,9 @@ public class LuaThread extends LuaValue {
|
|||||||
public final State state;
|
public final State state;
|
||||||
|
|
||||||
public static final int MAX_CALLSTACK = 256;
|
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.
|
/** 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 Object callstack;
|
||||||
|
|
||||||
public final Globals globals;
|
public final Globals globals;
|
||||||
@@ -244,6 +245,15 @@ public class LuaThread extends LuaValue {
|
|||||||
this.result = LuaValue.NONE;
|
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 {
|
public class CoroutineLib extends TwoArgFunction {
|
||||||
|
|
||||||
static long thread_orphan_check_interval = 30000;
|
|
||||||
|
|
||||||
static int coroutine_count = 0;
|
static int coroutine_count = 0;
|
||||||
|
|
||||||
Globals globals;
|
Globals globals;
|
||||||
|
|||||||
@@ -388,61 +388,55 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onCall(LuaFunction f) {
|
public void onCall(LuaFunction f) {
|
||||||
LuaThread t = globals.running;
|
if (globals.running.inhook) return;
|
||||||
if (t.inhook) return;
|
|
||||||
callstack().onCall(f);
|
callstack().onCall(f);
|
||||||
if (t.hookcall && t.hookfunc != null)
|
callHook(globals.running.hookfunc, CALL, NIL);
|
||||||
callHook(CALL, NIL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) {
|
public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) {
|
||||||
LuaThread t = globals.running;
|
if (globals.running.inhook) return;
|
||||||
if (t.inhook) return;
|
|
||||||
callstack().onCall(c, varargs, stack);
|
callstack().onCall(c, varargs, stack);
|
||||||
if (t.hookcall && t.hookfunc != null)
|
callHook(globals.running.hookfunc, CALL, NIL);
|
||||||
callHook(CALL, NIL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onInstruction(int pc, Varargs v, int top) {
|
public void onInstruction(int pc, Varargs v, int top) {
|
||||||
LuaThread t = globals.running;
|
if (globals.running.inhook) return;
|
||||||
if (t.inhook) return;
|
|
||||||
callstack().onInstruction(pc, v, top);
|
callstack().onInstruction(pc, v, top);
|
||||||
if (t.hookfunc == null) return;
|
if (globals.running.hookfunc == null) return;
|
||||||
if (t.hookcount > 0)
|
if (globals.running.hookcount > 0)
|
||||||
if (++t.bytecodes % t.hookcount == 0)
|
if (++globals.running.bytecodes % globals.running.hookcount == 0)
|
||||||
callHook(COUNT, NIL);
|
callHook(globals.running.hookfunc, COUNT, NIL);
|
||||||
if (t.hookline) {
|
if (globals.running.hookline) {
|
||||||
int newline = callstack().currentline();
|
int newline = callstack().currentline();
|
||||||
if ( newline != t.lastline ) {
|
if ( newline != globals.running.lastline ) {
|
||||||
t.lastline = newline;
|
globals.running.lastline = newline;
|
||||||
callHook(LINE, LuaValue.valueOf(newline));
|
callHook(globals.running.hookfunc, LINE, LuaValue.valueOf(newline));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onReturn() {
|
public void onReturn() {
|
||||||
LuaThread t = globals.running;
|
if (globals.running.inhook) return;
|
||||||
if (t.inhook) return;
|
|
||||||
callstack().onReturn();
|
callstack().onReturn();
|
||||||
if (t.hookcall && t.hookfunc != null)
|
callHook(globals.running.hookfunc, RETURN, NIL);
|
||||||
callHook(RETURN, NIL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String traceback(int level) {
|
public String traceback(int level) {
|
||||||
return callstack().traceback(level);
|
return callstack().traceback(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void callHook(LuaValue type, LuaValue arg) {
|
void callHook(LuaValue hookfunc, LuaValue type, LuaValue arg) {
|
||||||
LuaThread t = globals.running;
|
if (hookfunc == null) return;
|
||||||
t.inhook = true;
|
LuaThread.State state = globals.running.state;
|
||||||
|
state.set_inhook(true);
|
||||||
try {
|
try {
|
||||||
t.hookfunc.call(type, arg);
|
hookfunc.call(type, arg);
|
||||||
} catch (LuaError e) {
|
} catch (LuaError e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw new LuaError(e);
|
throw new LuaError(e);
|
||||||
} finally {
|
} finally {
|
||||||
t.inhook = false;
|
state.set_inhook(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user