Make error message handler in xpcall per-thread instead of per-globals.

This commit is contained in:
James Roseborough
2013-12-31 00:44:55 +00:00
parent b0d52fe118
commit 03985ec7ee
5 changed files with 40 additions and 36 deletions

View File

@@ -910,6 +910,7 @@ Files are no longer hosted at LuaForge.
<li>Implement formatting with os.date(), and table argument for os.time().</li>
<li>Refactor APIs related to compiling and loading scripts.</li>
<li>Let errors thrown in debug hooks bubble up to the running coroutine.</li>
<li>Make error function in xpcall per-thread instead of per-globals.</li>
</ul></td></tr>
</table></td></tr></table>

View File

@@ -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. */

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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,14 +360,27 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
// "xpcall", // (f, err) -> result1, ...
final class xpcall extends VarArgFunction {
public Varargs invoke(Varargs args) {
final LuaThread t = globals.running;
final LuaValue preverror = t.errorfunc;
t.errorfunc = args.checkvalue(2);
try {
if (globals != null && globals.debuglib != null)
globals.debuglib.onCall(this);
try {
return pcall(args.arg1(),args.subargs(3),args.checkvalue(2));
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;
}
}
}
@@ -397,24 +417,6 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
}
}
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
* @param env