BUG/MEDIUM: httpclient/lua: crash when the lua task timeout before the httpclient

When the lua task finished  before the httpclient that are associated to
it, there is a risk that the httpclient try to task_wakeup() the lua
task which does not exist anymore.

To fix this issue the httpclient used in a lua task are stored in a
list, and the httpclient are destroyed at the end of the lua task.

Must be backported in 2.5 and 2.6.
This commit is contained in:
William Lallemand 2022-10-20 10:57:28 +02:00
parent 321d100cc8
commit bb581423b3
2 changed files with 26 additions and 1 deletions

View File

@ -111,6 +111,7 @@ struct hlua {
struct task *task; /* The task associated with the lua stack execution.
We must wake this task to continue the task execution */
struct list com; /* The list head of the signals attached to this task. */
struct list hc_list; /* list of httpclient associated to this lua task */
struct ebpt_node node;
int gc_count; /* number of items which need a GC */
};
@ -198,6 +199,7 @@ struct hlua_httpclient {
struct httpclient *hc; /* ptr to the httpclient instance */
size_t sent; /* payload sent */
luaL_Buffer b; /* buffer used to prepare strings. */
struct list by_hlua; /* linked in the current hlua task */
};
#else /* USE_LUA */

View File

@ -1248,6 +1248,7 @@ int hlua_ctx_init(struct hlua *lua, int state_id, struct task *task, int already
lua->wake_time = TICK_ETERNITY;
lua->state_id = state_id;
LIST_INIT(&lua->com);
LIST_INIT(&lua->hc_list);
if (!already_safe) {
if (!SET_SAFE_LJMP_PARENT(lua)) {
lua->Tref = LUA_REFNIL;
@ -1269,6 +1270,20 @@ int hlua_ctx_init(struct hlua *lua, int state_id, struct task *task, int already
return 1;
}
/* kill all associated httpclient to this hlua task */
static void hlua_httpclient_destroy_all(struct hlua *hlua)
{
struct hlua_httpclient *hlua_hc, *back;
list_for_each_entry_safe(hlua_hc, back, &hlua->hc_list, by_hlua) {
if (hlua_hc->hc)
httpclient_stop_and_destroy(hlua_hc->hc);
hlua_hc->hc = NULL;
LIST_DELETE(&hlua_hc->by_hlua);
}
}
/* Used to destroy the Lua coroutine when the attached stream or task
* is destroyed. The destroy also the memory context. The struct "lua"
* is not freed.
@ -1281,6 +1296,9 @@ void hlua_ctx_destroy(struct hlua *lua)
if (!lua->T)
goto end;
/* clean all running httpclient */
hlua_httpclient_destroy_all(lua);
/* Purge all the pending signals. */
notification_purge(&lua->com);
@ -7012,7 +7030,10 @@ __LJMP static int hlua_httpclient_gc(lua_State *L)
hlua_hc = MAY_LJMP(hlua_checkhttpclient(L, 1));
httpclient_stop_and_destroy(hlua_hc->hc);
if (hlua_hc->hc)
httpclient_stop_and_destroy(hlua_hc->hc);
LIST_DELETE(&hlua_hc->by_hlua);
hlua_hc->hc = NULL;
@ -7046,6 +7067,8 @@ __LJMP static int hlua_httpclient_new(lua_State *L)
if (!hlua_hc->hc)
goto err;
LIST_APPEND(&hlua->hc_list, &hlua_hc->by_hlua);
/* Pop a class stream metatable and affect it to the userdata. */
lua_rawgeti(L, LUA_REGISTRYINDEX, class_httpclient_ref);
lua_setmetatable(L, -2);