diff options
Diffstat (limited to 'src/lua/lua_thread_pool.c')
-rw-r--r-- | src/lua/lua_thread_pool.c | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/src/lua/lua_thread_pool.c b/src/lua/lua_thread_pool.c index 979b31f6b..4c1681f96 100644 --- a/src/lua/lua_thread_pool.c +++ b/src/lua/lua_thread_pool.c @@ -91,6 +91,11 @@ lua_thread_pool_return (struct lua_thread_pool *pool, struct thread_entry *threa if (g_queue_get_length (pool->available_items) <= pool->max_items) { thread_entry->cd = NULL; + thread_entry->finish_callback = NULL; + thread_entry->error_callback = NULL; + thread_entry->task = NULL; + thread_entry->cfg = NULL; + g_queue_push_head (pool->available_items, thread_entry); } else { @@ -98,7 +103,7 @@ lua_thread_pool_return (struct lua_thread_pool *pool, struct thread_entry *threa } } -void +static void lua_thread_pool_terminate_entry (struct lua_thread_pool *pool, struct thread_entry *thread_entry) { struct thread_entry *ent = NULL; @@ -146,3 +151,88 @@ lua_thread_pool_restore_callback (struct lua_callback_state *cbs) lua_thread_pool_return (cbs->thread_pool, cbs->my_thread); lua_thread_pool_set_running_entry (cbs->thread_pool, cbs->previous_thread); } + +static gint +lua_do_resume (lua_State *L, gint narg) +{ +#if LUA_VERSION_NUM < 503 + return lua_resume (L, narg); +#else + return lua_resume (L, NULL, narg); +#endif +} + +static void lua_resume_thread_internal (struct thread_entry *thread_entry, gint narg); + +void +lua_thread_call (struct thread_entry *thread_entry, int narg) +{ + g_assert (lua_status (thread_entry->lua_state) == 0); /* we can't call running/yielded thread */ + g_assert (thread_entry->task != NULL || thread_entry->cfg != NULL); /* we can't call without pool */ + + lua_resume_thread_internal (thread_entry, narg); +} + +void +lua_resume_thread (struct thread_entry *thread_entry, gint narg) +{ + /* + * The only state where we can resume from is LUA_YIELD + * Another acceptable status is OK (0) but in that case we should push function on stack + * to start the thread from, which is happening in lua_thread_call(), not in this function. + */ + g_assert (lua_status (thread_entry->lua_state) == LUA_YIELD); + + lua_resume_thread_internal (thread_entry, narg); +} + +static void +lua_resume_thread_internal (struct thread_entry *thread_entry, gint narg) +{ + gint ret; + struct lua_thread_pool *pool; + GString *tb; + struct rspamd_task *task; + + ret = lua_do_resume (thread_entry->lua_state, narg); + + if (ret != LUA_YIELD) { + /* + LUA_YIELD state should not be handled here. + It should only happen when the thread initiated a asynchronous event and it will be restored as soon + the event is finished + */ + + if (thread_entry->task) { + pool = thread_entry->task->cfg->lua_thread_pool; + } + else { + pool = thread_entry->cfg->lua_thread_pool; + } + if (ret == 0) { + if (thread_entry->finish_callback) { + thread_entry->finish_callback (thread_entry, ret); + } + lua_thread_pool_return (pool, thread_entry); + } + else { + tb = rspamd_lua_get_traceback_string (thread_entry->lua_state); + if (thread_entry->error_callback) { + thread_entry->error_callback (thread_entry, ret, tb->str); + } + else if (thread_entry->task) { + task = thread_entry->task; + msg_err_task ("lua call failed (%d): %v", ret, tb); + } + else { + msg_err ("lua call failed (%d): %v", ret, tb); + } + + if (tb) { + g_string_free (tb, TRUE); + } + /* maybe there is a way to recover here. For now, just remove faulty thread */ + lua_thread_pool_terminate_entry (pool, thread_entry); + } + } +}
\ No newline at end of file |