From f501e948ae30787ce1d714abb6c25b9cf83939dd Mon Sep 17 00:00:00 2001 From: mniip Date: Mon, 4 Apr 2016 23:40:45 +0300 Subject: [PATCH] lua: Some more refactoring. Fix unload hook in the interpreter. --- plugins/lua/lua.c | 64 ++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/plugins/lua/lua.c b/plugins/lua/lua.c index c3f95a49..bbedf5d1 100644 --- a/plugins/lua/lua.c +++ b/plugins/lua/lua.c @@ -244,7 +244,7 @@ static void register_hook(hook_info *hook) static void free_hook(hook_info *hook) { - if (hook->state) + if(hook->state) luaL_unref(hook->state, LUA_REGISTRYINDEX, hook->ref); if(hook->hook) hexchat_unhook(ph, hook->hook); @@ -255,10 +255,10 @@ static int unregister_hook(hook_info *hook) { script_info *info = get_info(hook->state); - if (g_ptr_array_remove_fast(info->hooks, hook)) + if(g_ptr_array_remove_fast(info->hooks, hook)) return 1; - if (g_ptr_array_remove_fast(info->unload_hooks, hook)) + if(g_ptr_array_remove_fast(info->unload_hooks, hook)) return 1; return 0; @@ -1262,36 +1262,31 @@ static void prepare_state(lua_State *L, script_info *info) lua_pop(L, 1); } -struct unload_userdata { - lua_State *L; - int base; -}; - -static void run_unload_hook(hook_info *hook, struct unload_userdata *ud) +static void run_unload_hook(hook_info *hook, lua_State *L) { - lua_State *L = ud->L; - int base = ud->base; + int base = lua_gettop(L); lua_rawgeti(L, LUA_REGISTRYINDEX, hook->ref); if(lua_pcall(L, 0, 0, base)) { char const *error = lua_tostring(L, -1); - lua_pop(L, 2); hexchat_printf(ph, "Lua error in unload hook: %s", error ? error : "(non-string error)"); } + lua_settop(L, base); +} + +static void run_unload_hooks(script_info *info, void *unused) +{ + lua_State *L = info->state; + lua_rawgeti(L, LUA_REGISTRYINDEX, info->traceback); + g_ptr_array_foreach(info->unload_hooks, (GFunc)run_unload_hook, L); + lua_pop(L, 1); } static void destroy_script(script_info *info) { if (info) { - if (info->state) - { - struct unload_userdata data = {info->state, lua_gettop(info->state)}; - lua_rawgeti(info->state, LUA_REGISTRYINDEX, info->traceback); - g_ptr_array_foreach(info->unload_hooks, (GFunc)run_unload_hook, &data); - } - g_clear_pointer(&info->hooks, g_ptr_array_unref); g_clear_pointer(&info->unload_hooks, g_ptr_array_unref); g_clear_pointer(&info->state, lua_close); @@ -1394,7 +1389,10 @@ static int unload_script(char const *filename) if(script->status & STATUS_ACTIVE) script->status |= STATUS_DEFERRED_UNLOAD; else + { + run_unload_hooks(script, NULL); g_ptr_array_remove_fast(scripts, script); + } return 1; @@ -1412,6 +1410,7 @@ static int reload_script(char const *filename) else { char *filename = g_strdup(script->filename); + run_unload_hooks(script, NULL); g_ptr_array_remove_fast(scripts, script); load_script(filename); g_free(filename); @@ -1440,6 +1439,8 @@ static void create_interpreter(void) { lua_State *L; interp = g_new0(script_info, 1); + interp->hooks = g_ptr_array_new_with_free_func((GDestroyNotify)free_hook); + interp->unload_hooks = g_ptr_array_new_with_free_func((GDestroyNotify)free_hook); interp->name = "lua interpreter"; interp->description = ""; interp->version = ""; @@ -1461,7 +1462,6 @@ static void destroy_interpreter(void) { if(interp) { - lua_rawgeti(interp->state, LUA_REGISTRYINDEX, interp->traceback); g_clear_pointer(&interp->hooks, g_ptr_array_unref); g_clear_pointer(&interp->unload_hooks, g_ptr_array_unref); g_clear_pointer(&interp->state, lua_close); @@ -1558,18 +1558,21 @@ static void check_deferred(script_info *info) info->status &= ~STATUS_ACTIVE; if(info->status & STATUS_DEFERRED_UNLOAD) { + run_unload_hooks(info, NULL); g_ptr_array_remove_fast(scripts, info); } else if(info->status & STATUS_DEFERRED_RELOAD) { if(info == interp) { + run_unload_hooks(interp, NULL); destroy_interpreter(); create_interpreter(); } else { char *filename = g_strdup(info->filename); + run_unload_hooks(info, NULL); g_ptr_array_remove_fast(scripts, info); load_script(filename); g_free(filename); @@ -1612,13 +1615,15 @@ static int command_lua(char *word[], char *word_eol[], void *userdata) } else if(!strcmp(word[2], "reset")) { - if(interp->status & STATUS_ACTIVE) - interp->status |= STATUS_DEFERRED_RELOAD; - else - { - destroy_interpreter(); - create_interpreter(); - } + if(interp) + if(interp->status & STATUS_ACTIVE) + interp->status |= STATUS_DEFERRED_RELOAD; + else + { + run_unload_hooks(interp, NULL); + destroy_interpreter(); + create_interpreter(); + } } else if(!strcmp(word[2], "list")) { @@ -1680,14 +1685,17 @@ G_MODULE_EXPORT int hexchat_plugin_deinit(hexchat_plugin *plugin_handle) break; } } - if(!active && interp && interp->status & STATUS_ACTIVE) + if(interp && interp->status & STATUS_ACTIVE) active = TRUE; if(active) { hexchat_print(ph, "\00304Cannot unload the lua plugin while there are active states"); return 0; } + if(interp) + run_unload_hooks(interp, NULL); destroy_interpreter(); + g_ptr_array_foreach(scripts, (GFunc)run_unload_hooks, NULL); g_clear_pointer(&scripts, g_ptr_array_unref); g_clear_pointer(&expand_buffer, g_free); return 1;