lua: Some more refactoring. Fix unload hook in the interpreter.

This commit is contained in:
mniip 2016-04-04 23:40:45 +03:00 committed by Patrick Griffis
parent ba6a1190cd
commit f501e948ae
1 changed files with 36 additions and 28 deletions

View File

@ -244,7 +244,7 @@ static void register_hook(hook_info *hook)
static void free_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); luaL_unref(hook->state, LUA_REGISTRYINDEX, hook->ref);
if(hook->hook) if(hook->hook)
hexchat_unhook(ph, 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); 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; 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 1;
return 0; return 0;
@ -1262,36 +1262,31 @@ static void prepare_state(lua_State *L, script_info *info)
lua_pop(L, 1); lua_pop(L, 1);
} }
struct unload_userdata { static void run_unload_hook(hook_info *hook, lua_State *L)
lua_State *L;
int base;
};
static void run_unload_hook(hook_info *hook, struct unload_userdata *ud)
{ {
lua_State *L = ud->L; int base = lua_gettop(L);
int base = ud->base;
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->ref); lua_rawgeti(L, LUA_REGISTRYINDEX, hook->ref);
if(lua_pcall(L, 0, 0, base)) if(lua_pcall(L, 0, 0, base))
{ {
char const *error = lua_tostring(L, -1); 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)"); 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) static void destroy_script(script_info *info)
{ {
if (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->hooks, g_ptr_array_unref);
g_clear_pointer(&info->unload_hooks, g_ptr_array_unref); g_clear_pointer(&info->unload_hooks, g_ptr_array_unref);
g_clear_pointer(&info->state, lua_close); g_clear_pointer(&info->state, lua_close);
@ -1394,7 +1389,10 @@ static int unload_script(char const *filename)
if(script->status & STATUS_ACTIVE) if(script->status & STATUS_ACTIVE)
script->status |= STATUS_DEFERRED_UNLOAD; script->status |= STATUS_DEFERRED_UNLOAD;
else else
{
run_unload_hooks(script, NULL);
g_ptr_array_remove_fast(scripts, script); g_ptr_array_remove_fast(scripts, script);
}
return 1; return 1;
@ -1412,6 +1410,7 @@ static int reload_script(char const *filename)
else else
{ {
char *filename = g_strdup(script->filename); char *filename = g_strdup(script->filename);
run_unload_hooks(script, NULL);
g_ptr_array_remove_fast(scripts, script); g_ptr_array_remove_fast(scripts, script);
load_script(filename); load_script(filename);
g_free(filename); g_free(filename);
@ -1440,6 +1439,8 @@ static void create_interpreter(void)
{ {
lua_State *L; lua_State *L;
interp = g_new0(script_info, 1); 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->name = "lua interpreter";
interp->description = ""; interp->description = "";
interp->version = ""; interp->version = "";
@ -1461,7 +1462,6 @@ static void destroy_interpreter(void)
{ {
if(interp) if(interp)
{ {
lua_rawgeti(interp->state, LUA_REGISTRYINDEX, interp->traceback);
g_clear_pointer(&interp->hooks, g_ptr_array_unref); g_clear_pointer(&interp->hooks, g_ptr_array_unref);
g_clear_pointer(&interp->unload_hooks, g_ptr_array_unref); g_clear_pointer(&interp->unload_hooks, g_ptr_array_unref);
g_clear_pointer(&interp->state, lua_close); g_clear_pointer(&interp->state, lua_close);
@ -1558,18 +1558,21 @@ static void check_deferred(script_info *info)
info->status &= ~STATUS_ACTIVE; info->status &= ~STATUS_ACTIVE;
if(info->status & STATUS_DEFERRED_UNLOAD) if(info->status & STATUS_DEFERRED_UNLOAD)
{ {
run_unload_hooks(info, NULL);
g_ptr_array_remove_fast(scripts, info); g_ptr_array_remove_fast(scripts, info);
} }
else if(info->status & STATUS_DEFERRED_RELOAD) else if(info->status & STATUS_DEFERRED_RELOAD)
{ {
if(info == interp) if(info == interp)
{ {
run_unload_hooks(interp, NULL);
destroy_interpreter(); destroy_interpreter();
create_interpreter(); create_interpreter();
} }
else else
{ {
char *filename = g_strdup(info->filename); char *filename = g_strdup(info->filename);
run_unload_hooks(info, NULL);
g_ptr_array_remove_fast(scripts, info); g_ptr_array_remove_fast(scripts, info);
load_script(filename); load_script(filename);
g_free(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")) else if(!strcmp(word[2], "reset"))
{ {
if(interp->status & STATUS_ACTIVE) if(interp)
interp->status |= STATUS_DEFERRED_RELOAD; if(interp->status & STATUS_ACTIVE)
else interp->status |= STATUS_DEFERRED_RELOAD;
{ else
destroy_interpreter(); {
create_interpreter(); run_unload_hooks(interp, NULL);
} destroy_interpreter();
create_interpreter();
}
} }
else if(!strcmp(word[2], "list")) else if(!strcmp(word[2], "list"))
{ {
@ -1680,14 +1685,17 @@ G_MODULE_EXPORT int hexchat_plugin_deinit(hexchat_plugin *plugin_handle)
break; break;
} }
} }
if(!active && interp && interp->status & STATUS_ACTIVE) if(interp && interp->status & STATUS_ACTIVE)
active = TRUE; active = TRUE;
if(active) if(active)
{ {
hexchat_print(ph, "\00304Cannot unload the lua plugin while there are active states"); hexchat_print(ph, "\00304Cannot unload the lua plugin while there are active states");
return 0; return 0;
} }
if(interp)
run_unload_hooks(interp, NULL);
destroy_interpreter(); destroy_interpreter();
g_ptr_array_foreach(scripts, (GFunc)run_unload_hooks, NULL);
g_clear_pointer(&scripts, g_ptr_array_unref); g_clear_pointer(&scripts, g_ptr_array_unref);
g_clear_pointer(&expand_buffer, g_free); g_clear_pointer(&expand_buffer, g_free);
return 1; return 1;