degesch: Lua coroutine safety

This commit is contained in:
Přemysl Eric Janouch 2016-11-04 18:51:32 +01:00
parent 572f4e2ea3
commit 0247c4667a
Signed by: p
GPG Key ID: B715679E3A361BE6

View File

@ -8385,7 +8385,7 @@ static bool
lua_plugin_call (struct lua_plugin *self,
int n_params, int n_results, struct error **e)
{
// FIXME: this may be called from a thread, then this is wrong
// XXX: this may eventually be called from a thread, then this is wrong
lua_State *L = self->L;
// We need to pop the error handler at the end
@ -8844,11 +8844,9 @@ lua_weak_invalidate (void *object, void *user_data)
}
static void
lua_weak_push (struct lua_plugin *plugin, void *object,
lua_weak_push (lua_State *L, struct lua_plugin *plugin, void *object,
struct lua_weak_info *info)
{
// FIXME: this may be called from a thread, then this is wrong
lua_State *L = plugin->L;
if (!object)
{
lua_pushnil (L);
@ -8937,7 +8935,7 @@ lua_user_get_channels (lua_State *L)
lua_newtable (L);
LIST_FOR_EACH (struct user_channel, iter, user->channels)
{
lua_weak_push (wrapper->plugin, iter->channel, &lua_channel_info);
lua_weak_push (L, wrapper->plugin, iter->channel, &lua_channel_info);
lua_rawseti (L, -2, i++);
}
return 1;
@ -8969,7 +8967,7 @@ lua_channel_get_users (lua_State *L)
LIST_FOR_EACH (struct channel_user, iter, channel->users)
{
lua_createtable (L, 0, 2);
lua_weak_push (wrapper->plugin, iter->user, &lua_user_info);
lua_weak_push (L, wrapper->plugin, iter->user, &lua_user_info);
lua_setfield (L, -2, "user");
lua_plugin_kv (L, "prefixes", iter->prefixes.str);
@ -9153,9 +9151,9 @@ lua_input_hook_filter (struct input_hook *self, struct buffer *buffer,
lua_State *L = plugin->L;
lua_rawgeti (L, LUA_REGISTRYINDEX, hook->ref_callback);
lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook
lua_weak_push (plugin, buffer, &lua_buffer_info); // 2: buffer
lua_pushstring (L, input); // 3: input
lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook
lua_weak_push (L, plugin, buffer, &lua_buffer_info); // 2: buffer
lua_pushstring (L, input); // 3: input
struct error *e = NULL;
if (lua_plugin_call (plugin, 3, 1, &e))
@ -9177,9 +9175,9 @@ lua_irc_hook_filter (struct irc_hook *self, struct server *s, char *message)
lua_State *L = plugin->L;
lua_rawgeti (L, LUA_REGISTRYINDEX, hook->ref_callback);
lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook
lua_weak_push (plugin, s, &lua_server_info); // 2: server
lua_pushstring (L, message); // 3: message
lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook
lua_weak_push (L, plugin, s, &lua_server_info); // 2: server
lua_pushstring (L, message); // 3: message
struct error *e = NULL;
if (lua_plugin_call (plugin, 3, 1, &e))
@ -9287,7 +9285,7 @@ lua_completion_hook_complete (struct completion_hook *self,
lua_rawgetp (L, LUA_REGISTRYINDEX, hook); // 1: hook
lua_plugin_push_completion (L, data); // 2: data
lua_weak_push (plugin, plugin->ctx->current_buffer, &lua_buffer_info);
lua_weak_push (L, plugin, plugin->ctx->current_buffer, &lua_buffer_info);
lua_setfield (L, -2, "buffer");
lua_pushstring (L, word); // 3: word
@ -9325,11 +9323,9 @@ lua_timer_hook_dispatch (void *user_data)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static struct lua_hook *
lua_plugin_push_hook (struct lua_plugin *plugin, int callback_index,
enum lua_hook_type type, int priority)
lua_plugin_push_hook (lua_State *L, struct lua_plugin *plugin,
int callback_index, enum lua_hook_type type, int priority)
{
// FIXME: this may be called from a thread, then this is wrong
lua_State *L = plugin->L;
luaL_checktype (L, callback_index, LUA_TFUNCTION);
struct lua_hook *hook = lua_newuserdata (L, sizeof *hook);
@ -9352,7 +9348,7 @@ lua_plugin_hook_input (lua_State *L)
{
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
struct lua_hook *hook = lua_plugin_push_hook
(plugin, 1, XLUA_HOOK_INPUT, luaL_optinteger (L, 2, 0));
(L, plugin, 1, XLUA_HOOK_INPUT, luaL_optinteger (L, 2, 0));
hook->data.input_hook.filter = lua_input_hook_filter;
plugin->ctx->input_hooks =
hook_insert (plugin->ctx->input_hooks, &hook->data.hook);
@ -9364,7 +9360,7 @@ lua_plugin_hook_irc (lua_State *L)
{
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
struct lua_hook *hook = lua_plugin_push_hook
(plugin, 1, XLUA_HOOK_IRC, luaL_optinteger (L, 2, 0));
(L, plugin, 1, XLUA_HOOK_IRC, luaL_optinteger (L, 2, 0));
hook->data.irc_hook.filter = lua_irc_hook_filter;
plugin->ctx->irc_hooks =
hook_insert (plugin->ctx->irc_hooks, &hook->data.hook);
@ -9376,7 +9372,7 @@ lua_plugin_hook_prompt (lua_State *L)
{
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
struct lua_hook *hook = lua_plugin_push_hook
(plugin, 1, XLUA_HOOK_PROMPT, luaL_optinteger (L, 2, 0));
(L, plugin, 1, XLUA_HOOK_PROMPT, luaL_optinteger (L, 2, 0));
hook->data.prompt_hook.make = lua_prompt_hook_make;
plugin->ctx->prompt_hooks =
hook_insert (plugin->ctx->prompt_hooks, &hook->data.hook);
@ -9389,7 +9385,7 @@ lua_plugin_hook_completion (lua_State *L)
{
struct lua_plugin *plugin = lua_touserdata (L, lua_upvalueindex (1));
struct lua_hook *hook = lua_plugin_push_hook
(plugin, 1, XLUA_HOOK_COMPLETION, luaL_optinteger (L, 2, 0));
(L, plugin, 1, XLUA_HOOK_COMPLETION, luaL_optinteger (L, 2, 0));
hook->data.c_hook.complete = lua_completion_hook_complete;
plugin->ctx->completion_hooks =
hook_insert (plugin->ctx->completion_hooks, &hook->data.hook);
@ -9407,7 +9403,7 @@ lua_plugin_hook_timer (lua_State *L)
// This doesn't really hook anything but we can reuse the code
struct lua_hook *hook = lua_plugin_push_hook
(plugin, 1, XLUA_HOOK_TIMER, 0 /* priority doesn't apply */);
(L, plugin, 1, XLUA_HOOK_TIMER, 0 /* priority doesn't apply */);
struct poller_timer *timer = &hook->data.timer;
poller_timer_init (timer, &plugin->ctx->poller);
@ -9572,13 +9568,10 @@ lua_plugin_check_field (lua_State *L, int idx, const char *name,
}
static int
lua_plugin_add_config_schema (struct lua_plugin *plugin,
lua_plugin_add_config_schema (lua_State *L, struct lua_plugin *plugin,
struct config_item *subtree, const char *name)
{
struct config_item *item = str_map_find (&subtree->value.object, name);
// FIXME: this may be called from a thread, then this is wrong
lua_State *L = plugin->L;
// This should only ever happen because of a conflict with another plugin;
// this is the price we pay for simplicity
if (item && item->schema)
@ -9682,7 +9675,7 @@ lua_plugin_setup_config (lua_State *L)
return luaL_error (L, "%s: %s -> %s", "invalid types",
lua_typename (L, lua_type (L, -2)),
lua_typename (L, lua_type (L, -1)));
lua_plugin_add_config_schema (plugin, subtree, lua_tostring (L, -2));
lua_plugin_add_config_schema (L, plugin, subtree, lua_tostring (L, -2));
}
// Let the plugin read out configuration via on_change callbacks
@ -10140,17 +10133,17 @@ lua_plugin_panic (lua_State *L)
}
static void
lua_plugin_push_ref (struct lua_plugin *self, void *object,
lua_plugin_push_ref (lua_State *L, struct lua_plugin *self, void *object,
struct ispect_field *field)
{
// We create a mapping on object type registration
hard_assert (lua_rawgetp (self->L, LUA_REGISTRYINDEX, field->fields));
struct lua_weak_info *info = lua_touserdata (self->L, -1);
lua_pop (self->L, 1);
hard_assert (lua_rawgetp (L, LUA_REGISTRYINDEX, field->fields));
struct lua_weak_info *info = lua_touserdata (L, -1);
lua_pop (L, 1);
if (!field->is_list)
{
lua_weak_push (self, object, info);
lua_weak_push (L, self, object, info);
return;
}
@ -10158,25 +10151,25 @@ lua_plugin_push_ref (struct lua_plugin *self, void *object,
struct list_header { LIST_HEADER (void) };
int i = 1;
lua_newtable (self->L);
lua_newtable (L);
LIST_FOR_EACH (struct list_header, iter, object)
{
lua_weak_push (self, iter, info);
lua_rawseti (self->L, -2, i++);
lua_weak_push (L, self, iter, info);
lua_rawseti (L, -2, i++);
}
}
static void lua_plugin_push_map_field (struct lua_plugin *self,
static void lua_plugin_push_map_field (lua_State *L, struct lua_plugin *self,
const char *key, void *p, struct ispect_field *field);
static void
lua_plugin_push_struct (struct lua_plugin *self, enum ispect_type type,
void *value, struct ispect_field *field)
lua_plugin_push_struct (lua_State *L, struct lua_plugin *self,
enum ispect_type type, void *value, struct ispect_field *field)
{
if (type == ISPECT_STR)
{
struct str *s = value;
lua_pushlstring (self->L, s->str, s->len);
lua_pushlstring (L, s->str, s->len);
return;
}
if (type == ISPECT_STR_MAP)
@ -10185,16 +10178,16 @@ lua_plugin_push_struct (struct lua_plugin *self, enum ispect_type type,
str_map_iter_init (&iter, value);
void *value;
lua_newtable (self->L);
lua_newtable (L);
while ((value = str_map_iter_next (&iter)))
lua_plugin_push_map_field (self, iter.link->key, value, field);
lua_plugin_push_map_field (L, self, iter.link->key, value, field);
return;
}
hard_assert (!"unhandled introspection object type");
}
static void
lua_plugin_push_map_field (struct lua_plugin *self,
lua_plugin_push_map_field (lua_State *L, struct lua_plugin *self,
const char *key, void *p, struct ispect_field *field)
{
// That would mean maps in maps ad infinitum
@ -10204,15 +10197,15 @@ lua_plugin_push_map_field (struct lua_plugin *self,
switch (field->subtype)
{
// Here the types are generally casted to a void pointer
case ISPECT_BOOL: lua_pushboolean (self->L, (bool ) n); break;
case ISPECT_INT: lua_pushinteger (self->L, (int ) n); break;
case ISPECT_UINT: lua_pushinteger (self->L, (unsigned ) n); break;
case ISPECT_SIZE: lua_pushinteger (self->L, (size_t ) n); break;
case ISPECT_STRING: lua_pushstring (self->L, p); break;
case ISPECT_REF: lua_plugin_push_ref (self, p, field); break;
default: lua_plugin_push_struct (self, field->subtype, p, field);
case ISPECT_BOOL: lua_pushboolean (L, (bool ) n); break;
case ISPECT_INT: lua_pushinteger (L, (int ) n); break;
case ISPECT_UINT: lua_pushinteger (L, (unsigned ) n); break;
case ISPECT_SIZE: lua_pushinteger (L, (size_t ) n); break;
case ISPECT_STRING: lua_pushstring (L, p); break;
case ISPECT_REF: lua_plugin_push_ref (L, self, p, field); break;
default: lua_plugin_push_struct (L, self, field->subtype, p, field);
}
lua_setfield (self->L, -2, key);
lua_setfield (L, -2, key);
}
static bool
@ -10241,8 +10234,8 @@ lua_plugin_property_get_ispect (lua_State *L, const char *property_name)
case ISPECT_UINT: lua_pushinteger (L, *(unsigned *) p); break;
case ISPECT_SIZE: lua_pushinteger (L, *(size_t *) p); break;
case ISPECT_STRING: lua_pushstring (L, *(char **) p); break;
case ISPECT_REF: lua_plugin_push_ref (self, *(void **) p, field); break;
default: lua_plugin_push_struct (self, field->type, p, field);
case ISPECT_REF: lua_plugin_push_ref (L, self, *(void **) p, field); break;
default: lua_plugin_push_struct (L, self, field->type, p, field);
}
return true;
}
@ -10376,7 +10369,7 @@ lua_plugin_load (struct app_context *ctx, const char *filename,
lua_setfield (L, -2, "async");
lua_pop (L, 1);
lua_weak_push (plugin, ctx, &lua_ctx_info);
lua_weak_push (L, plugin, ctx, &lua_ctx_info);
lua_setglobal (L, lua_ctx_info.name);
// Create metatables for our objects