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:
parent
321d100cc8
commit
bb581423b3
@ -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 */
|
||||
|
25
src/hlua.c
25
src/hlua.c
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user