diff options
-rw-r--r-- | src/core/wee-command.c | 7 | ||||
-rw-r--r-- | src/core/wee-hook.c | 165 | ||||
-rw-r--r-- | src/core/wee-hook.h | 3 | ||||
-rw-r--r-- | src/plugins/alias/alias.c | 28 |
4 files changed, 168 insertions, 35 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 69ae10b29..a6e5d6d31 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -1149,7 +1149,7 @@ command_reload (void *data, void *buffer, gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); else gui_chat_printf (NULL, - _("%sError: failed to read WeeChat configuration " + _("%sError: failed to reload WeeChat configuration " "file"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); @@ -1159,8 +1159,11 @@ command_reload (void *data, void *buffer, gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); else gui_chat_printf (NULL, - _("%sError: failed to read plugins options"), + _("%sError: failed to reload plugins options"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); + + /* tell to plugins to reload their configuration */ + (void) hook_event_exec ("config_reload", NULL); return 0; } diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index 4ca24395c..f9d4d432e 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -40,6 +40,7 @@ struct t_hook *weechat_hooks = NULL; struct t_hook *last_weechat_hook = NULL; +int hook_exec_recursion = 0; /* @@ -111,6 +112,53 @@ hook_add_to_list (struct t_hook *new_hook) } /* + * hook_remove_from_list: remove a hook from list + */ + +void +hook_remove_from_list (struct t_hook *hook) +{ + struct t_hook *new_hooks; + + if (last_weechat_hook == hook) + last_weechat_hook = hook->prev_hook; + if (hook->prev_hook) + { + hook->prev_hook->next_hook = hook->next_hook; + new_hooks = weechat_hooks; + } + else + new_hooks = hook->next_hook; + + if (hook->next_hook) + hook->next_hook->prev_hook = hook->prev_hook; + + free (hook); + weechat_hooks = new_hooks; +} + +/* + * hook_remove_deleted: remove deleted hooks from list + */ + +void +hook_remove_deleted () +{ + struct t_hook *ptr_hook, *next_hook; + + ptr_hook = weechat_hooks; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if (ptr_hook->type == HOOK_TYPE_DELETED) + hook_remove_from_list (ptr_hook); + + ptr_hook = next_hook; + } +} + +/* * hook_init: init a new hook with default values */ @@ -277,7 +325,9 @@ hook_command_exec (void *buffer, char *string, int only_builtin) return -1; } argv_eol = string_explode (string, " ", 1, 0, NULL); - + + hook_exec_recursion++; + ptr_hook = weechat_hooks; while (ptr_hook) { @@ -296,8 +346,12 @@ hook_command_exec (void *buffer, char *string, int only_builtin) ptr_hook->running = 1; rc = (int) (HOOK_COMMAND(ptr_hook, callback)) (ptr_hook->callback_data, buffer, argc, argv, argv_eol); - if (hook_valid (ptr_hook)) + if (ptr_hook->type == HOOK_TYPE_COMMAND) ptr_hook->running = 0; + if (hook_exec_recursion > 0) + hook_exec_recursion--; + if (hook_exec_recursion == 0) + hook_remove_deleted (); if (rc == PLUGIN_RC_FAILED) return 0; else @@ -310,6 +364,12 @@ hook_command_exec (void *buffer, char *string, int only_builtin) string_free_exploded (argv); string_free_exploded (argv_eol); + if (hook_exec_recursion > 0) + hook_exec_recursion--; + + if (hook_exec_recursion == 0) + hook_remove_deleted (); + /* no hook found */ return -1; } @@ -358,6 +418,8 @@ hook_timer_exec (struct timeval *tv_time) struct t_hook *ptr_hook, *next_hook; long time_diff; + hook_exec_recursion++; + ptr_hook = weechat_hooks; while (ptr_hook) { @@ -373,21 +435,29 @@ hook_timer_exec (struct timeval *tv_time) ptr_hook->running = 1; (void) (HOOK_TIMER(ptr_hook, callback)) (ptr_hook->callback_data); - if (hook_valid (ptr_hook)) - ptr_hook->running = 0; - HOOK_TIMER(ptr_hook, last_exec).tv_sec = tv_time->tv_sec; - HOOK_TIMER(ptr_hook, last_exec).tv_usec = tv_time->tv_usec; - if (HOOK_TIMER(ptr_hook, remaining_calls) > 0) + if (ptr_hook->type == HOOK_TYPE_TIMER) { - HOOK_TIMER(ptr_hook, remaining_calls)--; - if (HOOK_TIMER(ptr_hook, remaining_calls) == 0) - unhook (ptr_hook); + ptr_hook->running = 0; + HOOK_TIMER(ptr_hook, last_exec).tv_sec = tv_time->tv_sec; + HOOK_TIMER(ptr_hook, last_exec).tv_usec = tv_time->tv_usec; + if (HOOK_TIMER(ptr_hook, remaining_calls) > 0) + { + HOOK_TIMER(ptr_hook, remaining_calls)--; + if (HOOK_TIMER(ptr_hook, remaining_calls) == 0) + unhook (ptr_hook); + } } } } ptr_hook = next_hook; } + + if (hook_exec_recursion > 0) + hook_exec_recursion--; + + if (hook_exec_recursion == 0) + hook_remove_deleted (); } /* @@ -483,7 +553,9 @@ void hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) { struct t_hook *ptr_hook, *next_hook; - + + hook_exec_recursion++; + ptr_hook = weechat_hooks; while (ptr_hook) { @@ -500,12 +572,18 @@ hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) { ptr_hook->running = 1; (HOOK_FD(ptr_hook, callback)) (ptr_hook->callback_data); - if (hook_valid (ptr_hook)) + if (ptr_hook->type == HOOK_TYPE_FD) ptr_hook->running = 0; } ptr_hook = next_hook; } + + if (hook_exec_recursion > 0) + hook_exec_recursion--; + + if (hook_exec_recursion == 0) + hook_remove_deleted (); } /* @@ -566,6 +644,8 @@ hook_print_exec (void *buffer, time_t date, char *prefix, char *message) return; } + hook_exec_recursion++; + ptr_hook = weechat_hooks; while (ptr_hook) { @@ -584,12 +664,18 @@ hook_print_exec (void *buffer, time_t date, char *prefix, char *message) (ptr_hook->callback_data, buffer, date, (HOOK_PRINT(ptr_hook, strip_colors)) ? prefix_no_color : prefix, (HOOK_PRINT(ptr_hook, strip_colors)) ? message_no_color : message); - if (hook_valid (ptr_hook)) + if (ptr_hook->type == HOOK_TYPE_PRINT) ptr_hook->running = 0; } ptr_hook = next_hook; } + + if (hook_exec_recursion > 0) + hook_exec_recursion--; + + if (hook_exec_recursion == 0) + hook_remove_deleted (); } /* @@ -636,6 +722,8 @@ hook_event_exec (char *event, void *pointer) { struct t_hook *ptr_hook, *next_hook; + hook_exec_recursion++; + ptr_hook = weechat_hooks; while (ptr_hook) { @@ -649,12 +737,18 @@ hook_event_exec (char *event, void *pointer) ptr_hook->running = 1; (void) (HOOK_EVENT(ptr_hook, callback)) (ptr_hook->callback_data, event, pointer); - if (hook_valid (ptr_hook)) + if (ptr_hook->type == HOOK_TYPE_EVENT) ptr_hook->running = 0; } ptr_hook = next_hook; } + + if (hook_exec_recursion > 0) + hook_exec_recursion--; + + if (hook_exec_recursion == 0) + hook_remove_deleted (); } /* @@ -699,6 +793,8 @@ hook_config_exec (char *type, char *option, char *value) { struct t_hook *ptr_hook, *next_hook; + hook_exec_recursion++; + ptr_hook = weechat_hooks; while (ptr_hook) { @@ -716,12 +812,18 @@ hook_config_exec (char *type, char *option, char *value) ptr_hook->running = 1; (void) (HOOK_CONFIG(ptr_hook, callback)) (ptr_hook->callback_data, type, option, value); - if (hook_valid (ptr_hook)) + if (ptr_hook->type == HOOK_TYPE_CONFIG) ptr_hook->running = 0; } ptr_hook = next_hook; } + + if (hook_exec_recursion > 0) + hook_exec_recursion--; + + if (hook_exec_recursion == 0) + hook_remove_deleted (); } /* @@ -731,13 +833,17 @@ hook_config_exec (char *type, char *option, char *value) void unhook (struct t_hook *hook) { - struct t_hook *new_hooks, *ptr_hook; + struct t_hook *ptr_hook; /* free data */ if (hook->hook_data) { switch (hook->type) { + case HOOK_TYPE_DELETED: + /* hook will be deleted later, we do nothing here, hook data is + already free */ + break; case HOOK_TYPE_COMMAND: /* decrease level for command hooks with same command name and level higher than this one */ @@ -789,24 +895,19 @@ unhook (struct t_hook *hook) free ((struct t_hook_config *)hook->hook_data); break; } + hook->hook_data = NULL; } - /* remove hook from list */ - if (last_weechat_hook == hook) - last_weechat_hook = hook->prev_hook; - if (hook->prev_hook) + /* remove hook from list (if there's no hook exec pending) */ + if (hook_exec_recursion == 0) { - hook->prev_hook->next_hook = hook->next_hook; - new_hooks = weechat_hooks; + hook_remove_from_list (hook); } else - new_hooks = hook->next_hook; - - if (hook->next_hook) - hook->next_hook->prev_hook = hook->prev_hook; - - free (hook); - weechat_hooks = new_hooks; + { + /* there is one or more hook exec, then delete later */ + hook->type = HOOK_TYPE_DELETED; + } } /* @@ -857,8 +958,14 @@ hook_print_log () { log_printf ("\n"); log_printf ("[hook (addr:0x%X)]\n", ptr_hook); + log_printf (" plugin . . . . . . . . : 0x%X\n", ptr_hook->plugin); switch (ptr_hook->type) { + case HOOK_TYPE_DELETED: + log_printf (" type . . . . . . . . . : %d (hook deleted)\n", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X\n", ptr_hook->callback_data); + log_printf (" hook_data. . . . . . . : 0x%X\n", ptr_hook->hook_data); + break; case HOOK_TYPE_COMMAND: log_printf (" type . . . . . . . . . : %d (command)\n", ptr_hook->type); log_printf (" callback_data. . . . . : 0x%X\n", ptr_hook->callback_data); diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index 8df84de47..7bf23300b 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -24,7 +24,8 @@ enum t_hook_type { - HOOK_TYPE_COMMAND = 0, /* new command */ + HOOK_TYPE_DELETED = 0, /* used when hook is deleted */ + HOOK_TYPE_COMMAND, /* new command */ HOOK_TYPE_TIMER, /* timer */ HOOK_TYPE_FD, /* socket of file descriptor */ HOOK_TYPE_PRINT, /* printed message */ diff --git a/src/plugins/alias/alias.c b/src/plugins/alias/alias.c index 372006688..22d7c8277 100644 --- a/src/plugins/alias/alias.c +++ b/src/plugins/alias/alias.c @@ -37,6 +37,7 @@ static struct t_alias *alias_list = NULL; static struct t_alias *last_alias = NULL; static struct t_hook *alias_command = NULL; static struct t_hook *unalias_command = NULL; +static struct t_hook *config_reload = NULL; /* @@ -527,14 +528,30 @@ alias_config_read () } /* - * alias_config_reaload: reload alias configuration file + * alias_config_reaload_event_cb: reload alias configuration file */ static int -alias_config_reload () +alias_config_reload_event_cb (void *data, char *event, void *pointer) { + /* make C compiler happy */ + (void) data; + (void) event; + (void) pointer; + alias_free_all (); - return weechat_config_reload (alias_config_file); + if (weechat_config_reload (alias_config_file) == 0) + { + weechat_printf (NULL, + _("%sAlias configuration file reloaded"), + weechat_prefix ("info")); + return PLUGIN_RC_SUCCESS; + } + weechat_printf (NULL, + _("%sAlias: failed to reload alias configuration " + "file"), + weechat_prefix ("error")); + return PLUGIN_RC_FAILED; } /* @@ -711,6 +728,9 @@ weechat_plugin_init (struct t_weechat_plugin *plugin) "remove"), "%h", unalias_command_cb, NULL); + + config_reload = weechat_hook_event ("config_reload", + alias_config_reload_event_cb, NULL); return PLUGIN_RC_SUCCESS; } @@ -727,5 +747,7 @@ weechat_plugin_end () weechat_config_free (alias_config_file); weechat_unhook (alias_command); weechat_unhook (unalias_command); + weechat_unhook (config_reload); + return PLUGIN_RC_SUCCESS; } |