From ce2dbe1f201ad9b2b97aea630045fe458d3c68b8 Mon Sep 17 00:00:00 2001 From: Lourival Vieira Neto Date: Wed, 22 Nov 2023 22:47:18 +0000 Subject: [PATCH] fix reentrant case of luantik_run --- lib/luanotifier.c | 13 +++++++++---- lunatik.h | 31 +++++++++++++++---------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/luanotifier.c b/lib/luanotifier.c index b0346b68..7ac545c8 100644 --- a/lib/luanotifier.c +++ b/lib/luanotifier.c @@ -93,9 +93,13 @@ static int luanotifier_call(struct notifier_block *nb, unsigned long event, void luanotifier_t *notifier = container_of(nb, luanotifier_t, nb); int ret; - notifier->running = true; - lunatik_run(notifier->runtime, luanotifier_handler, ret, notifier, event, data); - notifier->running = false; + if (notifier->running) + lunatik_handle(notifier->runtime, luanotifier_handler, ret, notifier, event, data); + else { + notifier->running = true; + lunatik_run(notifier->runtime, luanotifier_handler, ret, notifier, event, data); + notifier->running = false; + } return ret; } @@ -109,7 +113,6 @@ static int luanotifier_new(lua_State *L, luanotifier_register_t register_fn, lua notifier = (luanotifier_t *)lua_newuserdatauv(L, sizeof(luanotifier_t), 1); notifier->runtime = lunatik_toruntime(L); notifier->nb.notifier_call = luanotifier_call; - notifier->running = false; notifier->unregister = unregister_fn; notifier->handler = handler_fn; @@ -119,8 +122,10 @@ static int luanotifier_new(lua_State *L, luanotifier_register_t register_fn, lua lua_pushvalue(L, -1); /* push userdata */ notifier->ud = luaL_ref(L, LUA_REGISTRYINDEX); /* pops userdata */ + notifier->running = true; /* notifier_call might be called directly (e.g., NETDEV_REGISTER) */ if (register_fn(¬ifier->nb) != 0) luaL_error(L, "couldn't create notifier"); + notifier->running = false; luaL_setmetatable(L, LUANOTIFIER_MT); return 1; /* userdata */ diff --git a/lunatik.h b/lunatik.h index e12e8969..a671fea7 100644 --- a/lunatik.h +++ b/lunatik.h @@ -82,23 +82,22 @@ static inline void lunatik_release(struct kref *kref) #define lunatik_cansleep(L) (!lunatik_getready(L) || lunatik_getsleep(L)) -#define lunatik_run(runtime, handler, ret, ...) \ +#define lunatik_handle(runtime, handler, ret, ...) \ do { \ - lua_State *L; \ - int unlocked = !lunatik_islocked(runtime); \ - if (likely(unlocked)) \ - lunatik_lock(runtime); \ - L = runtime->L; \ - if (unlikely(!L)) \ - ret = -ENXIO; \ - else { \ - int n; \ - n = lua_gettop(L); \ - ret = handler(L, ## __VA_ARGS__); \ - lua_settop(L, n); \ - } \ - if (likely(unlocked)) \ - lunatik_unlock(runtime); \ + lua_State *L = runtime->L; \ + int n = lua_gettop(L); \ + ret = handler(L, ## __VA_ARGS__); \ + lua_settop(L, n); \ +} while(0) + +#define lunatik_run(runtime, handler, ret, ...) \ +do { \ + lunatik_lock(runtime); \ + if (unlikely(!runtime->L)) \ + ret = -ENXIO; \ + else \ + lunatik_handle(runtime, handler, ret, ## __VA_ARGS__); \ + lunatik_unlock(runtime); \ } while(0) typedef struct lunatik_reg_s {