diff options
author | Mike Pall <mike> | 2023-04-16 18:13:48 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2023-04-16 18:13:48 +0200 |
commit | 1c279127050e86e99970100e9c42e0f09cd54ab7 (patch) | |
tree | efdc67dab9c461e3122b8bf99a13157be5daf02e /src/lj_gc.c | |
parent | 8bbd58e534522a7e1ab9ee2c0d7fb723741dd089 (diff) | |
download | luajit-1c279127050e86e99970100e9c42e0f09cd54ab7.tar.gz luajit-1c279127050e86e99970100e9c42e0f09cd54ab7.tar.bz2 luajit-1c279127050e86e99970100e9c42e0f09cd54ab7.zip |
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")
Diffstat (limited to 'src/lj_gc.c')
-rw-r--r-- | src/lj_gc.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/src/lj_gc.c b/src/lj_gc.c index 2fc52ec1..6c3187c3 100644 --- a/src/lj_gc.c +++ b/src/lj_gc.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "lj_trace.h" | 27 | #include "lj_trace.h" |
28 | #include "lj_dispatch.h" | 28 | #include "lj_dispatch.h" |
29 | #include "lj_vm.h" | 29 | #include "lj_vm.h" |
30 | #include "lj_vmevent.h" | ||
30 | 31 | ||
31 | #define GCSTEPSIZE 1024u | 32 | #define GCSTEPSIZE 1024u |
32 | #define GCSWEEPMAX 40 | 33 | #define GCSWEEPMAX 40 |
@@ -521,8 +522,13 @@ static void gc_call_finalizer(global_State *g, lua_State *L, | |||
521 | hook_restore(g, oldh); | 522 | hook_restore(g, oldh); |
522 | if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g); | 523 | if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g); |
523 | g->gc.threshold = oldt; /* Restore GC threshold. */ | 524 | g->gc.threshold = oldt; /* Restore GC threshold. */ |
524 | if (errcode) | 525 | if (errcode) { |
525 | lj_err_throw(L, errcode); /* Propagate errors. */ | 526 | ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */ |
527 | lj_vmevent_send(L, ERRFIN, | ||
528 | copyTV(L, L->top++, restorestack(L, errobj)); | ||
529 | ); | ||
530 | L->top--; | ||
531 | } | ||
526 | } | 532 | } |
527 | 533 | ||
528 | /* Finalize one userdata or cdata object from the mmudata list. */ | 534 | /* Finalize one userdata or cdata object from the mmudata list. */ |