aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2023-04-16 18:13:48 +0200
committerMike Pall <mike>2023-04-16 18:13:48 +0200
commit1c279127050e86e99970100e9c42e0f09cd54ab7 (patch)
treeefdc67dab9c461e3122b8bf99a13157be5daf02e
parent8bbd58e534522a7e1ab9ee2c0d7fb723741dd089 (diff)
downloadluajit-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")
-rw-r--r--src/Makefile.dep42
-rw-r--r--src/lib_aux.c33
-rw-r--r--src/lj_gc.c10
-rw-r--r--src/lj_vmevent.h7
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 @@
1lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ 1lib_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
4lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 4lib_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 \
124lj_gc.o: lj_gc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 124lj_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
128lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 128lj_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
244luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 244luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
245host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ 245host/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
323static 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)
339LUALIB_API lua_State *luaL_newstate(void) 352LUALIB_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. */
25typedef enum { 25typedef 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