Print errors from __gc finalizers instead of rethrowing them.

Finalizers are not supposed to throw errors -- this is undefined behavior.
Lua 5.1 - 5.3 and (previously) LuaJIT rethrow the error. This randomly
breaks some unrelated code that just happens to do an allocation. Bad.
Lua 5.4 catches the error and emits a warning instead. But warnings are
not enabled by default, so it fails silently. Even worse.
LuaJIT (now) catches the error and emits a VM event. The default event
handler function prints "ERROR in finalizer: ...".
Set a custom handler function with: jit.attach(handler, "errfin")
This commit is contained in:
Mike Pall
2023-04-16 18:13:48 +02:00
parent 8bbd58e534
commit 1c27912705
4 changed files with 64 additions and 28 deletions

View File

@@ -27,6 +27,7 @@
#include "lj_trace.h"
#include "lj_dispatch.h"
#include "lj_vm.h"
#include "lj_vmevent.h"
#define GCSTEPSIZE 1024u
#define GCSWEEPMAX 40
@@ -521,8 +522,13 @@ static void gc_call_finalizer(global_State *g, lua_State *L,
hook_restore(g, oldh);
if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g);
g->gc.threshold = oldt; /* Restore GC threshold. */
if (errcode)
lj_err_throw(L, errcode); /* Propagate errors. */
if (errcode) {
ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */
lj_vmevent_send(L, ERRFIN,
copyTV(L, L->top++, restorestack(L, errobj));
);
L->top--;
}
}
/* Finalize one userdata or cdata object from the mmudata list. */