@@ -254,6 +254,22 @@ extern void lua_do_longjmp(luai_jmpbuf env, int val)
254254#define LUAI_TRY_END (L ) \
255255 (L)->errorJmp = lj.previous; \
256256 if (lj.status) { \
257+ /* Log the error and re-throw path for diagnostics. */ \
258+ thrlua_log ((L ), DCRITICAL , \
259+ "LUAI_TRY_END: error status=%d in TRY block at %s:%d, " \
260+ "re-throwing with %s outer handler, L=%p" , \
261+ lj .status , lj .file , lj .line , \
262+ lj .previous ? "an" : "NO" , (void * )(L )); \
263+ /* Re-acquire the lock before re-throwing. The LUAI_TRY_FINALLY \
264+ * block has already called lua_unlock(), but luaD_throw() expects \
265+ * the lock to be held: if there is an outer error handler its \
266+ * FINALLY will lua_unlock(), and if there is no outer handler the \
267+ * panic path in luaD_throw() calls lua_unlock() explicitly. \
268+ * Without this re-lock we double-unlock the pthread mutex which \
269+ * is undefined behavior and corrupts the mutex on Linux/glibc, \
270+ * causing every subsequent lua_lock() on this lua_State to fail \
271+ * with EINVAL and abort(). */ \
272+ lua_lock ((L )); \
257273 luaD_throw ((L ), lj .status ); \
258274 } \
259275} while (0 )
0 commit comments