From 03985ec7eefcf5da82b4cf4ab2bd9e5f9bafe267 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Tue, 31 Dec 2013 00:44:55 +0000 Subject: [PATCH] Make error message handler in xpcall per-thread instead of per-globals. --- README.html | 1 + src/core/org/luaj/vm2/Globals.java | 3 -- src/core/org/luaj/vm2/LuaClosure.java | 16 ++++----- src/core/org/luaj/vm2/LuaThread.java | 6 +++- src/core/org/luaj/vm2/lib/BaseLib.java | 50 +++++++++++++------------- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/README.html b/README.html index 52a5b5d1..c28d45fa 100644 --- a/README.html +++ b/README.html @@ -910,6 +910,7 @@ Files are no longer hosted at LuaForge.
  • Implement formatting with os.date(), and table argument for os.time().
  • Refactor APIs related to compiling and loading scripts.
  • Let errors thrown in debug hooks bubble up to the running coroutine.
  • +
  • Make error function in xpcall per-thread instead of per-globals.
  • diff --git a/src/core/org/luaj/vm2/Globals.java b/src/core/org/luaj/vm2/Globals.java index bf98bdaf..db31f132 100644 --- a/src/core/org/luaj/vm2/Globals.java +++ b/src/core/org/luaj/vm2/Globals.java @@ -136,9 +136,6 @@ public class Globals extends LuaTable { /** The DebugLib instance loaded into this Globals, or null if debugging is not enabled */ public DebugLib debuglib; - /** The current error handler for this Globals */ - public LuaValue errorfunc; - /** Interface for module that converts a Prototype into a LuaFunction with an environment. */ public interface Loader { /** Convert the prototype into a LuaFunction with the supplied environment. */ diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java index 22e54db2..c257d386 100644 --- a/src/core/org/luaj/vm2/LuaClosure.java +++ b/src/core/org/luaj/vm2/LuaClosure.java @@ -519,16 +519,18 @@ public class LuaClosure extends LuaFunction { * @param msg the message to use in error hook processing. * */ String errorHook(String msg) { - if (globals == null || globals.errorfunc == null) - return msg; - LuaValue errfunc = globals.errorfunc; - globals.errorfunc = null; + if (globals == null ) return msg; + final LuaThread running = globals.running; + if (running == null) return msg; + final LuaValue errfunc = running.errorfunc; + if (errfunc == null) return msg; + running.errorfunc = null; try { return errfunc.call( LuaValue.valueOf(msg) ).tojstring(); } catch ( Throwable t ) { return "error in error handling"; } finally { - globals.errorfunc = errfunc; + running.errorfunc = errfunc; } } @@ -536,8 +538,6 @@ public class LuaClosure extends LuaFunction { le.fileline = (p.source != null? p.source.tojstring(): "?") + ":" + (p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?"); le.traceback = errorHook(le.getMessage()); - if (globals != null && globals.debuglib != null) - le.traceback = le.traceback + "\n" + globals.debuglib.traceback(le.level); } private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) { @@ -548,7 +548,7 @@ public class LuaClosure extends LuaFunction { for (int i = 0; i < n; ++i) if (openups[i] == null) return openups[i] = new UpValue(stack, idx); - this.error("No space for upvalue"); + error("No space for upvalue"); return null; } diff --git a/src/core/org/luaj/vm2/LuaThread.java b/src/core/org/luaj/vm2/LuaThread.java index 0bee9bb8..1575a600 100644 --- a/src/core/org/luaj/vm2/LuaThread.java +++ b/src/core/org/luaj/vm2/LuaThread.java @@ -93,8 +93,12 @@ public class LuaThread extends LuaValue { public final Globals globals; - // Hook function control state used by debug lib. + /** Hook function control state used by debug lib. */ public LuaValue hookfunc; + + /** Error message handler for this thread, if any. */ + public LuaValue errorfunc; + public boolean hookline; public boolean hookcall; public boolean hookrtrn; diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index 28f17145..5ad69a15 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -29,6 +29,7 @@ import org.luaj.vm2.Lua; import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; @@ -213,7 +214,13 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { if (globals != null && globals.debuglib != null) globals.debuglib.onCall(this); try { - return pcall(func,args.subargs(2),null); + return varargsOf(TRUE, func.invoke(args.subargs(2))); + } catch ( LuaError le ) { + final String m = le.getMessage(); + return varargsOf(FALSE, m!=null? valueOf(m): NIL); + } catch ( Exception e ) { + final String m = e.getMessage(); + return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); } finally { if (globals != null && globals.debuglib != null) globals.debuglib.onReturn(); @@ -353,13 +360,26 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { // "xpcall", // (f, err) -> result1, ... final class xpcall extends VarArgFunction { public Varargs invoke(Varargs args) { - if (globals != null && globals.debuglib != null) - globals.debuglib.onCall(this); + final LuaThread t = globals.running; + final LuaValue preverror = t.errorfunc; + t.errorfunc = args.checkvalue(2); try { - return pcall(args.arg1(),args.subargs(3),args.checkvalue(2)); - } finally { if (globals != null && globals.debuglib != null) - globals.debuglib.onReturn(); + globals.debuglib.onCall(this); + try { + return varargsOf(TRUE, args.arg1().invoke(args.subargs(3))); + } catch ( LuaError le ) { + final String m = le.getMessage(); + return varargsOf(FALSE, m!=null? valueOf(m): NIL); + } catch ( Exception e ) { + final String m = e.getMessage(); + return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + } finally { + if (globals != null && globals.debuglib != null) + globals.debuglib.onReturn(); + } + } finally { + t.errorfunc = preverror; } } } @@ -396,24 +416,6 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { return args.checktable(1).inext(args.arg(2)); } } - - public Varargs pcall(LuaValue func, Varargs args, LuaValue errorfunc) { - try { - LuaValue olderr = globals.errorfunc; - globals.errorfunc = errorfunc; - try { - return varargsOf(LuaValue.TRUE, func.invoke(args)); - } finally { - globals.errorfunc = olderr; - } - } catch ( LuaError le ) { - String m = le.getMessage(); - return varargsOf(FALSE, m!=null? valueOf(m): NIL); - } catch ( Exception e ) { - String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); - } - } /** * Load from a named file, returning the chunk or nil,error of can't load