]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: lua: the execution timeout is ignored in yield case
authorThierry FOURNIER <tfournier@exceliance.fr>
Thu, 5 Mar 2015 10:16:52 +0000 (11:16 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 5 Mar 2015 10:50:01 +0000 (11:50 +0100)
This patch check the expiration of the execution timeout for each
yield source, and test also the execution timeout before resuming
the execution of the Lua code.

src/hlua.c

index f444c1573f28d0498105c410328151d5602f7a63..4570bc94c0f6fae6ad98e3e3dc67ad8686051b62 100644 (file)
@@ -547,9 +547,7 @@ __LJMP void hlua_yieldk(lua_State *L, int nresults, int ctx,
        /* 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;
+       hlua->wake_time = tick_first(timeout, hlua->expire);
 
        hlua->flags |= flags;
 
@@ -674,6 +672,12 @@ static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
 
        HLUA_SET_RUN(lua);
 
+       /* If we want to resume the task, then check first the execution timeout.
+        * if it is reached, we can interrupt the Lua processing.
+        */
+       if (tick_is_expired(lua->expire, now_ms))
+               goto timeout_reached;
+
 resume_execution:
 
        /* This hook interrupts the Lua processing each 'hlua_nb_instruction'
@@ -690,30 +694,32 @@ resume_execution:
                break;
 
        case LUA_YIELD:
-               /* If the yield id received join  to the flag HLUA_CTRLYIELD,
-                * we check the Lua timeout execution.
+               /* Check if the execution timeout is expired. It it is the case, we
+                * break the Lua execution.
                 */
-               if (HLUA_IS_CTRLYIELDING(lua)) {
-                       /* If the timeout is expired, we break the Lua execution. */
-                       if (tick_is_expired(lua->expire, now_ms)) {
-                               lua_settop(lua->T, 0); /* Empty the stack. */
-                               if (!lua_checkstack(lua->T, 1)) {
-                                       ret = HLUA_E_ERR;
-                                       break;
-                               }
-                               lua_pushfstring(lua->T, "execution timeout");
-                               ret = HLUA_E_ERRMSG;
+               if (tick_is_expired(lua->expire, now_ms)) {
+
+timeout_reached:
+
+                       lua_settop(lua->T, 0); /* Empty the stack. */
+                       if (!lua_checkstack(lua->T, 1)) {
+                               ret = HLUA_E_ERR;
                                break;
                        }
-                       /* if the general yield is not allowed or if no task were
-                        * associated this the current Lua execution coroutine, we
-                        * resume the execution.
-                        */
+                       lua_pushfstring(lua->T, "execution timeout");
+                       ret = HLUA_E_ERRMSG;
+                       break;
+               }
+               /* Process the forced yield. if the general yield is not allowed or
+                * if no task were associated this the current Lua execution
+                * coroutine, we resume the execution. Else we want to return in the
+                * scheduler and we want to be waked up again, to continue the
+                * current Lua execution. So we schedule our own task.
+                */
+               if (HLUA_IS_CTRLYIELDING(lua)) {
                        if (!yield_allowed || !lua->task)
                                goto resume_execution;
-                       /* Re-schedule the task. */
                        task_wakeup(lua->task, TASK_WOKEN_MSG);
-
                }
                if (!yield_allowed) {
                        lua_settop(lua->T, 0); /* Empty the stack. */