从Lua调用可抛异常的C#委托时Linux Docker环境CLR崩溃如何解决?
你的代码逻辑本身没有问题,该问题是NLua底层依赖的KeraLua库在Linux环境下的跨Native/托管栈异常传递兼容性缺陷导致的。
问题根因
- Windows与Linux平台的.NET CLR对跨Native调用栈的异常传播处理逻辑存在差异:当你注册到Lua的托管委托抛出异常时,Linux环境下KeraLua的Native回调逻辑没有正确捕获并包装托管异常,导致异常直接穿透到Lua原生运行时的调用栈,触发CLR致命错误(错误码
0x80131506),因此你外层的托管catch块无法捕获到异常。 - Lua侧的
pcall无法解决该问题的原因是:pcall只能捕获Lua运行时层面的错误,而该崩溃发生在托管代码与Native代码的交互层,异常还未传递回Lua的错误处理逻辑时CLR已经被终止。
修复方案
你可以根据自己的场景选择以下任意一种方案解决:
- 在托管委托内部提前捕获所有异常,不要让异常直接穿透托管边界抛到NLua的Native交互层。你可以选择将异常信息转为Lua错误抛出,或者存储到自定义上下文变量中后续处理,示例代码如下:
System.Action invoke = () => { try { throw new System.Exception("message"); } catch (System.Exception ex) { // 转成Lua侧可捕获的错误,不会触发CLR崩溃 luaState.Error(ex.ToString()); // 也可以在这里自行处理异常,不抛出到Lua侧 } };
- 改用你已经测试验证过的直接注册Lua函数的方式替代委托注册,该注册路径的异常处理逻辑已经适配Linux平台。
- 升级NLua与KeraLua Nuget包到最新正式版,该跨平台异常传递缺陷已经在后续版本中修复。
- 替换Lua交互库为纯托管实现的MoonSharp,完全规避Native与托管交互的跨平台兼容性问题。
内容的提问来源于stack exchange,提问作者Taemyr
相关产品推荐
相关产品推荐

