diff --git a/degesch.c b/degesch.c index c8aa67f..d88b3bd 100644 --- a/degesch.c +++ b/degesch.c @@ -7601,7 +7601,7 @@ static luaL_Reg lua_hook_table[] = // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Append a traceback to all errors so that we can later extract it +/// Append a traceback to all errors so that we can later extract it static int lua_plugin_error_handler (lua_State *L) { @@ -7632,16 +7632,33 @@ lua_plugin_process_error (struct lua_plugin *self, const char *message, return false; } -// Convenience function; replaces the "original" string or produces an error +/// Call a Lua function and process errors using our special error handler static bool -lua_plugin_handle_string_filter_result (struct lua_plugin *self, - int result, char **original, bool utf8, struct error **e) +lua_plugin_call (struct lua_plugin *self, + int n_params, int n_results, struct error **e) +{ + lua_State *L = self->L; + lua_pushcfunction (L, lua_plugin_error_handler); + + int error_handler_idx = -n_params - 2; + lua_insert (L, error_handler_idx); + + if (!lua_pcall (L, n_params, n_results, error_handler_idx)) + return true; + + (void) lua_plugin_process_error (self, lua_tostring (L, -1), e); + lua_pop (L, 1); + return false; +} + +/// Convenience function; replaces the "original" string or produces an error +static bool +lua_plugin_handle_string_filter_result (struct lua_plugin *self, + char **original, bool utf8, struct error **e) { lua_State *L = self->L; - if (result) - return lua_plugin_process_error (self, lua_tostring (L, -1), e); if (lua_isnil (L, -1)) - return NULL; + return true; if (!lua_isstring (L, -1)) FAIL ("must return either a string or nil"); @@ -7659,6 +7676,15 @@ lua_plugin_handle_string_filter_result (struct lua_plugin *self, return true; } +static void +lua_plugin_log_error + (struct lua_plugin *self, const char *where, struct error *error) +{ + log_global_error (self->ctx, "Lua: plugin \"#s\": #s: #s", + self->super.name, where, error->message); + error_free (error); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static char * @@ -7670,24 +7696,19 @@ lua_input_hook_filter (struct input_hook *self, struct buffer *buffer, struct lua_plugin *plugin = hook->plugin; lua_State *L = plugin->L; - lua_pushcfunction (L, lua_plugin_error_handler); - lua_rawgeti (L, LUA_REGISTRYINDEX, hook->ref_callback); lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook lua_plugin_push_buffer (plugin, buffer); // 2: buffer lua_pushstring (L, input); // 3: input struct error *e = NULL; - bool failed = !lua_plugin_handle_string_filter_result - (plugin, lua_pcall (L, 3, 1, -5), &input, true, &e); - lua_pop (L, 1); - - if (failed) + if (lua_plugin_call (plugin, 3, 1, &e)) { - log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s", - plugin->super.name, "input hook", e->message); - error_free (e); + lua_plugin_handle_string_filter_result (plugin, &input, true, &e); + lua_pop (L, 1); } + if (e) + lua_plugin_log_error (plugin, "input hook", e); return input; } @@ -7706,24 +7727,19 @@ lua_irc_hook_filter (struct irc_hook *self, struct server *s, char *message) struct lua_plugin *plugin = hook->plugin; lua_State *L = plugin->L; - lua_pushcfunction (L, lua_plugin_error_handler); - lua_rawgeti (L, LUA_REGISTRYINDEX, hook->ref_callback); lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook lua_plugin_push_server (plugin, s); // 2: server lua_pushstring (L, message); // 3: message struct error *e = NULL; - bool failed = !lua_plugin_handle_string_filter_result - (plugin, lua_pcall (L, 3, 1, -5), &message, false, &e); - lua_pop (L, 1); - - if (failed) + if (lua_plugin_call (plugin, 3, 1, &e)) { - log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s", - plugin->super.name, "IRC hook", e->message); - error_free (e); + lua_plugin_handle_string_filter_result (plugin, &message, false, &e); + lua_pop (L, 1); } + if (e) + lua_plugin_log_error (plugin, "IRC hook", e); return message; } @@ -7741,21 +7757,12 @@ lua_timer_hook_dispatch (void *user_data) struct lua_plugin *plugin = hook->plugin; lua_State *L = plugin->L; - lua_pushcfunction (L, lua_plugin_error_handler); - lua_rawgeti (L, LUA_REGISTRYINDEX, hook->ref_callback); lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook - if (lua_pcall (L, 1, 0, -3)) - { - struct error *e = NULL; - (void) lua_plugin_process_error (plugin, lua_tostring (L, -1), &e); - lua_pop (L, 1); - - log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s", - plugin->super.name, "timer hook", e->message); - error_free (e); - } + struct error *e = NULL; + if (!lua_plugin_call (plugin, 1, 0, &e)) + lua_plugin_log_error (plugin, "timer hook", e); // There's no need to keep the hook around once the timer is dispatched lua_cache_invalidate (L, hook); @@ -7929,21 +7936,12 @@ lua_schema_item_validate (const struct config_item *item, struct error **e) if (self->ref_validate == LUA_REFNIL) return true; - struct lua_plugin *plugin = self->plugin; - lua_State *L = plugin->L; - - lua_pushcfunction (L, lua_plugin_error_handler); + lua_State *L = self->plugin->L; lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_validate); lua_plugin_push_config_item (L, item); // The callback can make use of error("...", 0) to produce nice messages - if (lua_pcall (L, 1, 0, -3)) - { - (void) lua_plugin_process_error (plugin, lua_tostring (L, -1), e); - lua_pop (L, 1); - return false; - } - return true; + return lua_plugin_call (self->plugin, 1, 0, e); } static void @@ -7953,23 +7951,13 @@ lua_schema_item_on_change (struct config_item *item) if (self->ref_on_change == LUA_REFNIL) return; - struct lua_plugin *plugin = self->plugin; - lua_State *L = plugin->L; - - lua_pushcfunction (L, lua_plugin_error_handler); + lua_State *L = self->plugin->L; lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_on_change); lua_plugin_push_config_item (L, item); - if (lua_pcall (L, 1, 0, -3)) - { - struct error *e = NULL; - (void) lua_plugin_process_error (plugin, lua_tostring (L, -1), &e); - lua_pop (L, 1); - - log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s", - plugin->super.name, "schema on_change", e->message); - error_free (e); - } + struct error *e = NULL; + if (!lua_plugin_call (self->plugin, 1, 0, &e)) + lua_plugin_log_error (self->plugin, "schema on_change", e); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8244,30 +8232,21 @@ static void lua_connector_on_connected (void *user_data, int socket, const char *hostname) { struct lua_connector *self = user_data; - struct lua_plugin *plugin = self->plugin; - lua_State *L = plugin->L; // TODO: use this for SNI once TLS is implemented (void) hostname; if (self->ref_on_success != LUA_REFNIL) { - lua_pushcfunction (L, lua_plugin_error_handler); - + lua_State *L = self->plugin->L; lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_on_success); - lua_plugin_push_connection (plugin, socket); // 1: connection + lua_plugin_push_connection (self->plugin, socket); // 1: connection - if (lua_pcall (L, 1, 0, -3)) - { - struct error *e = NULL; - (void) lua_plugin_process_error (plugin, lua_tostring (L, -1), &e); - lua_pop (L, 1); - - log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s", - plugin->super.name, "connector on_success", e->message); - error_free (e); - } + struct error *e = NULL; + if (!lua_plugin_call (self->plugin, 1, 0, &e)) + lua_plugin_log_error (self->plugin, "connector on_success", e); } + lua_connector_discard (self); } @@ -8275,27 +8254,17 @@ static void lua_connector_on_failure (void *user_data) { struct lua_connector *self = user_data; - struct lua_plugin *plugin = self->plugin; - lua_State *L = plugin->L; - if (self->ref_on_error != LUA_REFNIL) { - lua_pushcfunction (L, lua_plugin_error_handler); - + lua_State *L = self->plugin->L; lua_rawgeti (L, LUA_REGISTRYINDEX, self->ref_on_error); lua_pushstring (L, self->last_error); // 1: error string - if (lua_pcall (L, 1, 0, -3)) - { - struct error *e = NULL; - (void) lua_plugin_process_error (plugin, lua_tostring (L, -1), &e); - lua_pop (L, 1); - - log_global_error (plugin->ctx, "Lua: plugin \"#s\": #s: #s", - plugin->super.name, "connector on_error", e->message); - error_free (e); - } + struct error *e = NULL; + if (!lua_plugin_call (self->plugin, 1, 0, &e)) + lua_plugin_log_error (self->plugin, "connector on_error", e); } + lua_connector_discard (self); }