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

@ -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,10 +1615,12 @@ static int command_lua(char *word[], char *word_eol[], void *userdata)
}
else if(!strcmp(word[2], "reset"))
{
if(interp)
if(interp->status & STATUS_ACTIVE)
interp->status |= STATUS_DEFERRED_RELOAD;
else
{
run_unload_hooks(interp, NULL);
destroy_interpreter();
create_interpreter();
}
@ -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;