Skip to content

Commit

Permalink
Move call to lua_error to the same level of the delegate callback
Browse files Browse the repository at this point in the history
* Lua.Error() will call setjmp and this can cause a crash with CLR on Linux, it seems that calling the setjmp longjmp twice will crash on *nix systems.
This should make this issue work a bit better: #344
  • Loading branch information
viniciusjarina committed Jan 18, 2020
1 parent 09837ff commit ceac1a5
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/Lua.cs
Expand Up @@ -367,7 +367,7 @@ internal int SetPendingException(Exception e)
return 0;

_translator.ThrowError(_luaState, caughtExcept);
_luaState.PushNil();
//_luaState.PushNil();
return 1;
}

Expand Down
49 changes: 31 additions & 18 deletions src/Metatables.cs
Expand Up @@ -17,6 +17,7 @@

using LuaState = KeraLua.Lua;
using LuaNativeFunction = KeraLua.LuaFunction;
using NLua.Exceptions;

namespace NLua
{
Expand Down Expand Up @@ -84,8 +85,13 @@ private static int RunFunctionDelegate(IntPtr luaState)
var translator = ObjectTranslatorPool.Instance.Find(state);
var func = (LuaNativeFunction)translator.GetRawNetObject(state, 1);
state.Remove(1);
return func(luaState);
}
int result = func(luaState);
var exception = translator.GetObject(state, -1) as LuaScriptException;

if (exception != null)
return state.Error();
return result;
}

/*
* __gc metafunction of CLR objects.
Expand Down Expand Up @@ -221,7 +227,7 @@ static int UnaryNegationLua(LuaState luaState, ObjectTranslator translator)
if (obj1 == null)
{
translator.ThrowError(luaState, "Cannot negate a nil object");
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand All @@ -231,7 +237,7 @@ static int UnaryNegationLua(LuaState luaState, ObjectTranslator translator)
if (opUnaryNegation == null)
{
translator.ThrowError(luaState, "Cannot negate object (" + type.Name + " does not overload the operator -)");
luaState.PushNil();
//luaState.PushNil();
return 1;
}
obj1 = opUnaryNegation.Invoke(obj1, new [] { obj1 });
Expand Down Expand Up @@ -331,7 +337,7 @@ private int GetMethodInternal(LuaState luaState)
if (obj == null)
{
_translator.ThrowError(luaState, "Trying to index an invalid object reference");
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand Down Expand Up @@ -546,7 +552,7 @@ private int TryGetValueForKeyMethods(LuaState luaState, MethodInfo[] methods, ob
if (!found)
{
_translator.ThrowError(luaState, "key not found: " + index);
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand All @@ -561,7 +567,7 @@ private int TryGetValueForKeyMethods(LuaState luaState, MethodInfo[] methods, ob
else
_translator.ThrowError(luaState, "exception indexing '" + index + "' " + e.Message);

luaState.PushNil();
//luaState.PushNil();
return 1;
}
}
Expand Down Expand Up @@ -608,7 +614,7 @@ private int TryIndexMethods(LuaState luaState, MethodInfo [] methods, object obj
else
_translator.ThrowError(luaState, "exception indexing '" + index + "' " + e.Message);

luaState.PushNil();
//luaState.PushNil();
return 1;
}
}
Expand Down Expand Up @@ -637,8 +643,8 @@ private int GetBaseMethodInternal(LuaState luaState)
if (obj == null)
{
_translator.ThrowError(luaState, "Trying to index an invalid object reference");
luaState.PushNil();
luaState.PushBoolean(false);
//luaState.PushNil();
//luaState.PushBoolean(false);
return 2;
}

Expand Down Expand Up @@ -845,7 +851,7 @@ int GetMember(LuaState luaState, ProxyType objType, object obj, string methodNam
{
// If we reach this point we found a static method, but can't use it in this context because the user passed in an instance
_translator.ThrowError(luaState, "Can't pass instance to static method " + methodName);
luaState.PushNil();
//luaState.PushNil();
}
}
else
Expand All @@ -857,7 +863,8 @@ int GetMember(LuaState luaState, ProxyType objType, object obj, string methodNam
// is not sufficient. valid data members may return nil and therefore there must be some
// way to know the member just doesn't exist.
_translator.ThrowError(luaState, "Unknown member name " + methodName);
luaState.PushNil();
//luaState.PushNil();
return 1;
}

// Push false because we are NOT returning a function (see luaIndexFunction)
Expand Down Expand Up @@ -1128,7 +1135,7 @@ private int GetClassMethodInternal(LuaState luaState)
if (klass == null)
{
_translator.ThrowError(luaState, "Trying to index an invalid type reference");
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand Down Expand Up @@ -1170,7 +1177,7 @@ private int SetClassFieldOrPropertyInternal(LuaState luaState)
if (target == null)
{
_translator.ThrowError(luaState, "trying to index an invalid type reference");
return 0;
return 1;
}

return SetMember(luaState, target, null, BindingFlags.Static);
Expand All @@ -1187,7 +1194,13 @@ static int CallDelegate(IntPtr state)
var luaState = LuaState.FromIntPtr(state);
var translator = ObjectTranslatorPool.Instance.Find(luaState);
var instance = translator.MetaFunctionsInstance;
return instance.CallDelegateInternal(luaState);
int result = instance.CallDelegateInternal(luaState);
var exception = translator.GetObject(luaState, -1) as LuaScriptException;

if (exception != null)
return luaState.Error();

return result;
}

/*
Expand All @@ -1201,7 +1214,7 @@ static int CallInvalidMethod(IntPtr state)
var luaState = LuaState.FromIntPtr(state);
var translator = ObjectTranslatorPool.Instance.Find(luaState);
translator.ThrowError(luaState, "Trying to invoke invalid method or an access an invalid index");
luaState.PushNil();
luaState.Error();
return 1;
}

Expand Down Expand Up @@ -1236,7 +1249,7 @@ int CallDelegateInternal(LuaState luaState)
}

_translator.ThrowError(luaState, "Cannot invoke delegate (invalid arguments for " + methodDelegate.Name + ")");
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand Down Expand Up @@ -1347,7 +1360,7 @@ static int MatchOperator(LuaState luaState, string operation, ObjectTranslator t
if (target == null)
{
translator.ThrowError(luaState, "Cannot call " + operation + " on a nil object");
luaState.PushNil();
// luaState.PushNil();
return 1;
}

Expand Down
8 changes: 4 additions & 4 deletions src/Method/LuaMethodWrapper.cs
Expand Up @@ -220,7 +220,7 @@ int CallMethodFromName(LuaState luaState)
{
_translator.ThrowError(luaState,
string.Format("instance method '{0}' requires a non null target object", _methodName));
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand Down Expand Up @@ -251,7 +251,7 @@ int CallMethodFromName(LuaState luaState)
? "Invalid arguments to method call"
: ("Invalid arguments to method: " + candidateName);
_translator.ThrowError(luaState, msg);
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand Down Expand Up @@ -317,7 +317,7 @@ int Call(IntPtr state)
if (!_translator.MatchParameters(luaState, methodToCall, _lastCalledMethod, 0))
{
_translator.ThrowError(luaState, "Invalid arguments to method call");
luaState.PushNil();
//luaState.PushNil();
return 1;
}
}
Expand All @@ -327,7 +327,7 @@ int Call(IntPtr state)
{
_translator.ThrowError(luaState,
"Unable to invoke method on generic class as the current method is an open generic method");
luaState.PushNil();
//luaState.PushNil();
return 1;
}

Expand Down
2 changes: 1 addition & 1 deletion src/ObjectTranslator.cs
Expand Up @@ -239,7 +239,7 @@ internal void ThrowError(LuaState luaState, object e)
}

Push(luaState, e);
luaState.Error();
//luaState.Error();
}

/*
Expand Down
71 changes: 71 additions & 0 deletions tests/src/LuaTests.cs
Expand Up @@ -2711,6 +2711,77 @@ public void InvalidArrayIndex()
Assert.AreNotEqual(15, result, "#1");
}

[Test]
public void ThrowMultipleExceptions()
{
using (Lua lua = new Lua())
{
lua.DoString("luanet.load_assembly('mscorlib')");
lua.DoString("luanet.load_assembly('NLuaTest', 'NLuaTest.TestTypes')");
lua.DoString("TestClass = luanet.import_type('NLuaTest.TestTypes.TestClass')");
lua.DoString("test = TestClass()");
lua.DoString("err,errMsg = pcall(test.exceptionMethod,test)");
bool err = (bool)lua["err"];

var errMsg = (Exception)lua["errMsg"];
Assert.AreEqual(false, err);
Assert.AreNotEqual(null, errMsg.InnerException);
Assert.AreEqual("exception test", errMsg.InnerException.Message);

lua.DoString("err2,errMsg2 = pcall(test.exceptionMethod,test)");
err = (bool)lua["err2"];

errMsg = (Exception)lua["errMsg2"];
Assert.AreEqual(false, err);
Assert.AreNotEqual(null, errMsg.InnerException);
Assert.AreEqual("exception test", errMsg.InnerException.Message);
}
}

/*
* Tests capturing multiple exceptions in LuaFunction call
*/
[Test]
public void ThrowMultipleExceptionsInScript()
{
string script1 =
"function run()\n" +
" function callMethod() " +
" test:exceptionMethod() " +
" test:exceptionMethod() " +
" end" +
" err1, errMsg1 = pcall(callMethod);\n" +
// " err2, errMsg2 = pcall(callMethod);\n" +
"end ";

//string script2 = " err, errMsg = pcall(test.exceptionMethod,test);\n";

TestClass test = new TestClass();

using (Lua lua = new Lua())
{
lua["test"] = test;

//lua.DoString(script2);

//bool err = (bool)lua["err"];
//var errMsg = (Exception)lua["errMsg"];
//Assert.AreEqual(false, err);
//Assert.AreNotEqual(null, errMsg.InnerException);
//Assert.AreEqual("exception test", errMsg.InnerException.Message);

lua.DoString(script1);
(lua["run"] as LuaFunction).Call();
(lua["run"] as LuaFunction).Call();

bool err = (bool)lua["err1"];
var errMsg = (Exception)lua["errMsg1"];
Assert.AreEqual(false, err);
Assert.AreNotEqual(null, errMsg.InnerException);
Assert.AreEqual("exception test", errMsg.InnerException.Message);
}
}


static Lua m_lua;
}
Expand Down

0 comments on commit ceac1a5

Please sign in to comment.