MEDIUM: lua: each yielding function returns a wake up time.

This is used to ensure that the task doesn't become a zombie
when the Lua returns a yield. The yield wrapper ensure that an
timer used for waking up the task will be set.

The timer is reseted to TICK_ETERNITY if the Lua execution is
done.
diff --git a/include/types/hlua.h b/include/types/hlua.h
index 274659c..0e1b2fc 100644
--- a/include/types/hlua.h
+++ b/include/types/hlua.h
@@ -35,6 +35,7 @@
 	             -1 if the memory context is not used. */
 	int nargs; /* The number of arguments in the stack at the start of execution. */
 	unsigned int flags; /* The current execution flags. */
+	int wake_time; /* The lua wants to be waked at this time, or before. */
 	int expire; /* Lua execution must be stopped over this time. */
 	struct task *task; /* The task associated with the lua stack execution.
 	                      We must wake this task to continue the task execution */
diff --git a/src/hlua.c b/src/hlua.c
index 7bb5f9f..8f8f0bd 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -509,6 +509,25 @@
 	ebpt_insert(&hlua_ctx, &hlua->node);
 }
 
+/* This function just ensure that the yield will be always
+ * returned with a timeout and permit to set some flags
+ */
+__LJMP void hlua_yieldk(lua_State *L, int nresults, int ctx,
+                        lua_CFunction k, int timeout)
+{
+	struct hlua *hlua = hlua_gethlua(L);
+
+	/* Set the wake timeout. If timeout is required, we set
+	 * the expiration time.
+	 */
+	hlua->wake_time = timeout;
+	if (hlua->wake_time == TICK_ETERNITY)
+		hlua->wake_time = hlua->expire;
+
+	/* Process the yield. */
+	WILL_LJMP(lua_yieldk(L, nresults, ctx, k));
+}
+
 /* This function initialises the Lua environment stored in the session.
  * It must be called at the start of the session. This function creates
  * an LUA coroutine. It can not be use to crete the main LUA context.
@@ -644,6 +663,7 @@
 		break;
 
 	case LUA_ERRRUN:
+		lua->wake_time = TICK_ETERNITY;
 		if (!lua_checkstack(lua->T, 1)) {
 			ret = HLUA_E_ERR;
 			break;
@@ -659,6 +679,7 @@
 		break;
 
 	case LUA_ERRMEM:
+		lua->wake_time = TICK_ETERNITY;
 		lua_settop(lua->T, 0); /* Empty the stack. */
 		if (!lua_checkstack(lua->T, 1)) {
 			ret = HLUA_E_ERR;
@@ -669,6 +690,7 @@
 		break;
 
 	case LUA_ERRERR:
+		lua->wake_time = TICK_ETERNITY;
 		if (!lua_checkstack(lua->T, 1)) {
 			ret = HLUA_E_ERR;
 			break;
@@ -684,6 +706,7 @@
 		break;
 
 	default:
+		lua->wake_time = TICK_ETERNITY;
 		lua_settop(lua->T, 0); /* Empty the stack. */
 		if (!lua_checkstack(lua->T, 1)) {
 			ret = HLUA_E_ERR;
@@ -1133,7 +1156,7 @@
 	appctx = objt_appctx(socket->s->si[0].end);
 	if (!hlua_com_new(hlua, &appctx->ctx.hlua.wake_on_read))
 		WILL_LJMP(luaL_error(L, "out of memory"));
-	WILL_LJMP(lua_yieldk(L, 0, 0, hlua_socket_receive_yield));
+	WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY));
 	return 0;
 }
 
@@ -1283,7 +1306,7 @@
 	appctx = objt_appctx(socket->s->si[0].end);
 	if (!hlua_com_new(hlua, &appctx->ctx.hlua.wake_on_write))
 		WILL_LJMP(luaL_error(L, "out of memory"));
-	WILL_LJMP(lua_yieldk(L, 0, 0, hlua_socket_write_yield));
+	WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_write_yield, TICK_ETERNITY));
 	return 0;
 }
 
@@ -1513,7 +1536,7 @@
 
 	if (!hlua_com_new(hlua, &appctx->ctx.hlua.wake_on_write))
 		WILL_LJMP(luaL_error(L, "out of memory error"));
-	WILL_LJMP(lua_yieldk(L, 0, 0, hlua_socket_connect_yield));
+	WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY));
 	return 0;
 }
 
@@ -1553,7 +1576,7 @@
 	 */
 	task_wakeup(socket->s->task, TASK_WOKEN_INIT);
 
-	WILL_LJMP(lua_yieldk(L, 0, 0, hlua_socket_connect_yield));
+	WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY));
 
 	return 0;
 }
@@ -1938,7 +1961,7 @@
 	chn = MAY_LJMP(hlua_checkchannel(L, 1));
 
 	if (_hlua_channel_dup(chn, L) == 0)
-		WILL_LJMP(lua_yieldk(L, 0, 0, hlua_channel_dup));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_dup, TICK_ETERNITY));
 	return 1;
 }
 
@@ -1957,7 +1980,7 @@
 	chn = MAY_LJMP(hlua_checkchannel(L, 1));
 	ret = _hlua_channel_dup(chn, L);
 	if (unlikely(ret == 0))
-		WILL_LJMP(lua_yieldk(L, 0, 0, hlua_channel_get));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_get, TICK_ETERNITY));
 
 	if (unlikely(ret == -1))
 		return 1;
@@ -1987,7 +2010,7 @@
 
 	ret = bi_getline_nc(chn->chn, &blk1, &len1, &blk2, &len2);
 	if (ret == 0)
-		WILL_LJMP(lua_yieldk(L, 0, 0, hlua_channel_getline));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_getline, TICK_ETERNITY));
 
 	if (ret == -1) {
 		lua_pushnil(L);
@@ -2032,7 +2055,7 @@
 		return 1;
 	}
 	if (ret == -1)
-		WILL_LJMP(lua_yieldk(L, 0, 0, _hlua_channel_append));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, _hlua_channel_append, TICK_ETERNITY));
 	l += ret;
 	lua_pop(L, 1);
 	lua_pushinteger(L, l);
@@ -2046,7 +2069,7 @@
 		return 1;
 	}
 	if (l < len)
-		WILL_LJMP(lua_yieldk(L, 0, 0, _hlua_channel_append));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, _hlua_channel_append, TICK_ETERNITY));
 	return 1;
 }
 
@@ -2122,7 +2145,7 @@
 		return 1;
 	}
 	if (l < len)
-		WILL_LJMP(lua_yieldk(L, 0, 0, _hlua_channel_send));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, _hlua_channel_send, TICK_ETERNITY));
 
 	return 1;
 }
@@ -2175,7 +2198,7 @@
 			return 1;
 
 		/* Otherwise, we can yield waiting for new data in the inpout side. */
-		WILL_LJMP(lua_yieldk(L, 0, 0, hlua_channel_forward_yield));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_forward_yield, TICK_ETERNITY));
 	}
 
 	return 1;
@@ -2497,7 +2520,7 @@
 {
 	int wakeup_ms = lua_tointeger(L, -1);
 	if (now_ms < wakeup_ms)
-		WILL_LJMP(lua_yieldk(L, 0, 0, hlua_sleep_yield));
+		WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, TICK_ETERNITY));
 	return 0;
 }
 
@@ -2536,7 +2559,7 @@
 	/* Store the wakeup time in the lua stack. */
 	lua_pushinteger(L, t->wakeup_ms);
 
-	WILL_LJMP(lua_yieldk(L, 0, 0, hlua_sleep_yield));
+	WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, TICK_ETERNITY));
 	return 0;
 }
 
@@ -2634,7 +2657,9 @@
 		task_free(task);
 		break;
 
-	case HLUA_E_AGAIN: /* co process wake me later. */
+	case HLUA_E_AGAIN: /* co process or timeout wake me later. */
+		if (hlua->wake_time != TICK_ETERNITY)
+			task_schedule(task, hlua->wake_time);
 		break;
 
 	/* finished with error. */
@@ -3178,6 +3203,13 @@
 
 	/* yield. */
 	case HLUA_E_AGAIN:
+		/* Set timeout in the required channel. */
+		if (s->hlua.wake_time != TICK_ETERNITY) {
+			if (analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE))
+				s->req->analyse_exp = s->hlua.wake_time;
+			else if (analyzer & (AN_RES_INSPECT|AN_RES_HTTP_PROCESS_BE))
+				s->rep->analyse_exp = s->hlua.wake_time;
+		}
 		/* Some actions can be wake up when a "write" event
 		 * is detected on a response channel. This is useful
 		 * only for actions targetted on the requests.