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 | |
| 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')
| -rw-r--r-- | src/Makefile.dep | 42 | ||||
| -rw-r--r-- | src/lib_aux.c | 33 | ||||
| -rw-r--r-- | src/lj_gc.c | 10 | ||||
| -rw-r--r-- | src/lj_vmevent.h | 7 |
4 files changed, 64 insertions, 28 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep index 1ad6701a..400ef8b0 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ | 1 | lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ |
| 2 | lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ | 2 | lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ |
| 3 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h | 3 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lj_vmevent.h |
| 4 | lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 4 | lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
| 5 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h \ | 5 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h \ |
| 6 | lj_str.h lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h \ | 6 | lj_str.h lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h \ |
| @@ -124,7 +124,7 @@ lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | |||
| 124 | lj_gc.o: lj_gc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 124 | lj_gc.o: lj_gc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 125 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ | 125 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ |
| 126 | lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h \ | 126 | lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h \ |
| 127 | lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h | 127 | lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_vmevent.h |
| 128 | lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 128 | lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 129 | lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_buf.h \ | 129 | lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_buf.h \ |
| 130 | lj_str.h lj_strfmt.h lj_jit.h lj_ir.h lj_dispatch.h | 130 | lj_str.h lj_strfmt.h lj_jit.h lj_ir.h lj_dispatch.h |
| @@ -222,25 +222,25 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \ | |||
| 222 | lj_def.h lj_arch.h lj_gc.c lj_gc.h lj_err.h lj_errmsg.h lj_buf.h \ | 222 | lj_def.h lj_arch.h lj_gc.c lj_gc.h lj_err.h lj_errmsg.h lj_buf.h \ |
| 223 | lj_str.h lj_tab.h lj_func.h lj_udata.h lj_meta.h lj_state.h lj_frame.h \ | 223 | lj_str.h lj_tab.h lj_func.h lj_udata.h lj_meta.h lj_state.h lj_frame.h \ |
| 224 | lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ | 224 | lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ |
| 225 | lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ | 225 | lj_traceerr.h lj_vm.h lj_vmevent.h lj_err.c lj_debug.h lj_ff.h \ |
| 226 | lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ | 226 | lj_ffdef.h lj_strfmt.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c \ |
| 227 | lj_prng.h lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h \ | 227 | lj_buf.c lj_str.c lj_prng.h lj_tab.c lj_func.c lj_udata.c lj_meta.c \ |
| 228 | lj_debug.c lj_prng.c lj_state.c lj_lex.h lj_alloc.h luajit.h \ | 228 | lj_strscan.h lj_lib.h lj_debug.c lj_prng.c lj_state.c lj_lex.h \ |
| 229 | lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \ | 229 | lj_alloc.h luajit.h lj_dispatch.c lj_ccallback.h lj_profile.h \ |
| 230 | lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_serialize.c \ | 230 | lj_vmevent.c lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c \ |
| 231 | lj_serialize.h lj_api.c lj_profile.c lj_lex.c lualib.h lj_parse.h \ | 231 | lj_serialize.c lj_serialize.h lj_api.c lj_profile.c lj_lex.c lualib.h \ |
| 232 | lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c \ | 232 | lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c \ |
| 233 | lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c \ | 233 | lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h \ |
| 234 | lj_target.h lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c \ | 234 | lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h lj_carith.c \ |
| 235 | lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h \ | 235 | lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c \ |
| 236 | lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \ | 236 | lj_ircall.h lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h \ |
| 237 | lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c \ | 237 | lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c \ |
| 238 | lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ | 238 | lj_opt_sink.c lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h \ |
| 239 | lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ | 239 | lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \ |
| 240 | lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ | 240 | lj_emit_*.h lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c \ |
| 241 | lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ | 241 | lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c \ |
| 242 | lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ | 242 | lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c \ |
| 243 | lib_buffer.c lib_init.c | 243 | lib_ffi.c lib_buffer.c lib_init.c |
| 244 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h | 244 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h |
| 245 | host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ | 245 | host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ |
| 246 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ | 246 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ |
diff --git a/src/lib_aux.c b/src/lib_aux.c index b8e56436..7b01693a 100644 --- a/src/lib_aux.c +++ b/src/lib_aux.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include "lj_state.h" | 21 | #include "lj_state.h" |
| 22 | #include "lj_trace.h" | 22 | #include "lj_trace.h" |
| 23 | #include "lj_lib.h" | 23 | #include "lj_lib.h" |
| 24 | #include "lj_vmevent.h" | ||
| 24 | 25 | ||
| 25 | #if LJ_TARGET_POSIX | 26 | #if LJ_TARGET_POSIX |
| 26 | #include <sys/wait.h> | 27 | #include <sys/wait.h> |
| @@ -318,6 +319,18 @@ static int panic(lua_State *L) | |||
| 318 | return 0; | 319 | return 0; |
| 319 | } | 320 | } |
| 320 | 321 | ||
| 322 | #ifndef LUAJIT_DISABLE_VMEVENT | ||
| 323 | static int error_finalizer(lua_State *L) | ||
| 324 | { | ||
| 325 | const char *s = lua_tostring(L, -1); | ||
| 326 | fputs("ERROR in finalizer: ", stderr); | ||
| 327 | fputs(s ? s : "?", stderr); | ||
| 328 | fputc('\n', stderr); | ||
| 329 | fflush(stderr); | ||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | #endif | ||
| 333 | |||
| 321 | #ifdef LUAJIT_USE_SYSMALLOC | 334 | #ifdef LUAJIT_USE_SYSMALLOC |
| 322 | 335 | ||
| 323 | #if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND) | 336 | #if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND) |
| @@ -339,7 +352,15 @@ static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize) | |||
| 339 | LUALIB_API lua_State *luaL_newstate(void) | 352 | LUALIB_API lua_State *luaL_newstate(void) |
| 340 | { | 353 | { |
| 341 | lua_State *L = lua_newstate(mem_alloc, NULL); | 354 | lua_State *L = lua_newstate(mem_alloc, NULL); |
| 342 | if (L) G(L)->panic = panic; | 355 | if (L) { |
| 356 | G(L)->panic = panic; | ||
| 357 | #ifndef LUAJIT_DISABLE_VMEVENT | ||
| 358 | luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE); | ||
| 359 | lua_pushcfunction(L, error_finalizer); | ||
| 360 | lua_rawseti(L, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN)); | ||
| 361 | G(L)->vmevmask = VMEVENT_MASK(LJ_VMEVENT_ERRFIN); | ||
| 362 | #endif | ||
| 363 | } | ||
| 343 | return L; | 364 | return L; |
| 344 | } | 365 | } |
| 345 | 366 | ||
| @@ -353,7 +374,15 @@ LUALIB_API lua_State *luaL_newstate(void) | |||
| 353 | #else | 374 | #else |
| 354 | L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL); | 375 | L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL); |
| 355 | #endif | 376 | #endif |
| 356 | if (L) G(L)->panic = panic; | 377 | if (L) { |
| 378 | G(L)->panic = panic; | ||
| 379 | #ifndef LUAJIT_DISABLE_VMEVENT | ||
| 380 | luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE); | ||
| 381 | lua_pushcfunction(L, error_finalizer); | ||
| 382 | lua_rawseti(L, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN)); | ||
| 383 | G(L)->vmevmask = VMEVENT_MASK(LJ_VMEVENT_ERRFIN); | ||
| 384 | #endif | ||
| 385 | } | ||
| 357 | return L; | 386 | return L; |
| 358 | } | 387 | } |
| 359 | 388 | ||
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. */ |
diff --git a/src/lj_vmevent.h b/src/lj_vmevent.h index 40f9c631..c08a26dc 100644 --- a/src/lj_vmevent.h +++ b/src/lj_vmevent.h | |||
| @@ -24,9 +24,10 @@ | |||
| 24 | /* VM event IDs. */ | 24 | /* VM event IDs. */ |
| 25 | typedef enum { | 25 | typedef enum { |
| 26 | VMEVENT_DEF(BC, 0x00003883), | 26 | VMEVENT_DEF(BC, 0x00003883), |
| 27 | VMEVENT_DEF(TRACE, 0xb2d91467), | 27 | VMEVENT_DEF(TRACE, 0x12d91467), |
| 28 | VMEVENT_DEF(RECORD, 0x9284bf4f), | 28 | VMEVENT_DEF(RECORD, 0x1284bf4f), |
| 29 | VMEVENT_DEF(TEXIT, 0xb29df2b0), | 29 | VMEVENT_DEF(TEXIT, 0x129df2b0), |
| 30 | VMEVENT_DEF(ERRFIN, 0x12d93888), | ||
| 30 | LJ_VMEVENT__MAX | 31 | LJ_VMEVENT__MAX |
| 31 | } VMEvent; | 32 | } VMEvent; |
| 32 | 33 | ||
