diff options
-rw-r--r-- | doc/ext_ffi_semantics.html | 16 | ||||
-rw-r--r-- | src/lj_ccallback.c | 10 |
2 files changed, 23 insertions, 3 deletions
diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index f8da1e60..ab02f2b8 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html | |||
@@ -934,6 +934,22 @@ advisable in general. Do this only if you know the C function, that | |||
934 | called the callback, copes with the forced stack unwinding and doesn't | 934 | called the callback, copes with the forced stack unwinding and doesn't |
935 | leak resources. | 935 | leak resources. |
936 | </p> | 936 | </p> |
937 | <p> | ||
938 | One thing that's not allowed, is to let an FFI call into a C function | ||
939 | get JIT-compiled, which in turn calls a callback, calling into Lua again. | ||
940 | Usually this attempt is caught by the interpreter first and the | ||
941 | C function is blacklisted for compilation. | ||
942 | </p> | ||
943 | <p> | ||
944 | However, this heuristic may fail under specific circumstances: e.g. a | ||
945 | message polling function might not run Lua callbacks right away and the call | ||
946 | gets JIT-compiled. If it later happens to call back into Lua, you'll get a | ||
947 | VM PANIC with the message <tt>"bad callback"</tt>. Then you'll need to | ||
948 | manually turn off JIT-compilation with | ||
949 | <a href="ext_jit.html#jit_onoff_func"><tt>jit.off()</tt></a> for the | ||
950 | surrounding Lua function that invokes such a message polling function (or | ||
951 | similar). | ||
952 | </p> | ||
937 | 953 | ||
938 | <h3 id="callback_resources">Callback resource handling</h3> | 954 | <h3 id="callback_resources">Callback resource handling</h3> |
939 | <p> | 955 | <p> |
diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c index 430643ee..e1d03fcf 100644 --- a/src/lj_ccallback.c +++ b/src/lj_ccallback.c | |||
@@ -527,10 +527,14 @@ static void callback_conv_result(CTState *cts, lua_State *L, TValue *o) | |||
527 | lua_State * LJ_FASTCALL lj_ccallback_enter(CTState *cts, void *cf) | 527 | lua_State * LJ_FASTCALL lj_ccallback_enter(CTState *cts, void *cf) |
528 | { | 528 | { |
529 | lua_State *L = cts->L; | 529 | lua_State *L = cts->L; |
530 | global_State *g = cts->g; | ||
530 | lua_assert(L != NULL); | 531 | lua_assert(L != NULL); |
531 | if (gcref(cts->g->jit_L)) | 532 | if (gcref(g->jit_L)) { |
532 | lj_err_caller(gco2th(gcref(cts->g->jit_L)), LJ_ERR_FFI_BADCBACK); | 533 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_FFI_BADCBACK)); |
533 | lj_trace_abort(cts->g); /* Never record across callback. */ | 534 | if (g->panic) g->panic(L); |
535 | exit(EXIT_FAILURE); | ||
536 | } | ||
537 | lj_trace_abort(g); /* Never record across callback. */ | ||
534 | /* Setup C frame. */ | 538 | /* Setup C frame. */ |
535 | cframe_prev(cf) = L->cframe; | 539 | cframe_prev(cf) = L->cframe; |
536 | setcframe_L(cf, L); | 540 | setcframe_L(cf, L); |