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.
diff --git a/include/haproxy/hlua-t.h b/include/haproxy/hlua-t.h
index 82204fe..bc8c8df 100644
--- a/include/haproxy/hlua-t.h
+++ b/include/haproxy/hlua-t.h
@@ -111,6 +111,7 @@
 	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 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 */
diff --git a/src/hlua.c b/src/hlua.c
index 70be127..9b646bc 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -1248,6 +1248,7 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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 @@
 	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);