]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: applet: now call si_applet_done() instead of si_update() in I/O handlers
authorWilly Tarreau <w@1wt.eu>
Sun, 19 Apr 2015 15:20:03 +0000 (17:20 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 23 Apr 2015 15:56:16 +0000 (17:56 +0200)
The applet I/O handlers now rely on si_applet_done() which itself decides
to wake up or sleep the appctx. Now it becomes critical that applte handlers
properly call this on every exit path so that the appctx is removed from the
active list after I/O have been handled. One such call was added to the Lua
socket handler. It used to work without it probably because the main task is
woken up by the parent task but now it's needed.

src/dumpstats.c
src/hlua.c
src/peers.c
src/stream_interface.c

index 0a2bd6747d60fe4e8d55c4eb1516a90ca34eb5eb..809025f2bae9cd700fa01ef29dd62037e0cc4ab0 100644 (file)
@@ -2428,14 +2428,14 @@ static void cli_io_handler(struct appctx *appctx)
                res->flags |= CF_READ_NULL;
        }
 
+ out:
        /* update all other flags and resync with the other side */
-       si_update(si);
+       si_applet_done(si);
 
        /* we don't want to expire timeouts while we're processing requests */
        si_ic(si)->rex = TICK_ETERNITY;
        si_oc(si)->wex = TICK_ETERNITY;
 
- out:
        DPRINTF(stderr, "%s@%d: st=%d, rqf=%x, rpf=%x, rqh=%d, rqs=%d, rh=%d, rs=%d\n",
                __FUNCTION__, __LINE__,
                si->state, req->flags, res->flags, req->buf->i, req->buf->o, res->buf->i, res->buf->o);
@@ -4897,7 +4897,7 @@ static void http_stats_io_handler(struct appctx *appctx)
                        if (bi_putchk(si_ic(si), &trash) == -1) {
                                si->flags |= SI_FL_WAIT_ROOM;
                                si_ic(si)->to_forward = last_fwd;
-                               goto fail;
+                               goto out;
                        }
                }
 
@@ -4948,7 +4948,7 @@ static void http_stats_io_handler(struct appctx *appctx)
                        chunk_printf(&trash, "\r\n0\r\n\r\n");
                        if (bi_putchk(si_ic(si), &trash) == -1) {
                                si->flags |= SI_FL_WAIT_ROOM;
-                               goto fail;
+                               goto out;
                        }
                }
                /* eat the whole request */
@@ -4967,15 +4967,14 @@ static void http_stats_io_handler(struct appctx *appctx)
                }
        }
 
fail:
out:
        /* update all other flags and resync with the other side */
-       si_update(si);
+       si_applet_done(si);
 
        /* we don't want to expire timeouts while we're processing requests */
        si_ic(si)->rex = TICK_ETERNITY;
        si_oc(si)->wex = TICK_ETERNITY;
 
- out:
        if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO)) {
                /* check that we have released everything then unregister */
                stream_int_unregister_handler(si);
index 68f0a3928ea02e9e3498efc165003fb145bc5616..fb006e6e1ebf32eaacb0f5adb7e613f14b9f84bb 100644 (file)
@@ -1446,11 +1446,11 @@ static void hlua_socket_handler(struct appctx *appctx)
                si_ic(si)->flags |= CF_READ_NULL;
                hlua_com_wake(&appctx->ctx.hlua.wake_on_read);
                hlua_com_wake(&appctx->ctx.hlua.wake_on_write);
-               return;
+               goto leave;
        }
 
        if (!(c->flags & CO_FL_CONNECTED))
-               return;
+               goto leave;
 
        /* This function is called after the connect. */
        appctx->ctx.hlua.connected = 1;
@@ -1462,6 +1462,9 @@ static void hlua_socket_handler(struct appctx *appctx)
        /* Wake the tasks which wants to read if the buffer contains data. */
        if (channel_is_empty(si_ic(si)))
                hlua_com_wake(&appctx->ctx.hlua.wake_on_read);
+
+ leave:
+       si_applet_done(si);
 }
 
 /* This function is called when the "struct stream" is destroyed.
@@ -1631,7 +1634,7 @@ __LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua
        bo_skip(oc, len + skip_at_end);
 
        /* Don't wait anything. */
-       si_update(&socket->s->si[0]);
+       si_applet_done(&socket->s->si[0]);
 
        /* If the pattern reclaim to read all the data
         * in the connection, got out.
@@ -1808,7 +1811,7 @@ static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext
        }
 
        /* update buffers. */
-       si_update(&socket->s->si[0]);
+       si_applet_done(&socket->s->si[0]);
        socket->s->req.rex = TICK_ETERNITY;
        socket->s->res.wex = TICK_ETERNITY;
 
index 2a927e0da8a6bc92dc58b8aeb7778b304c2b4731..97a87289da4ff0c928b2c74b02729a8d7ffaa478 100644 (file)
@@ -1038,17 +1038,16 @@ incomplete:
                                si_shutw(si);
                                si_shutr(si);
                                si_ic(si)->flags |= CF_READ_NULL;
-                               goto quit;
+                               goto out;
                        }
                }
        }
 out:
-       si_update(si);
+       si_applet_done(si);
        si_oc(si)->flags |= CF_READ_DONTWAIT;
        /* we don't want to expire timeouts while we're processing requests */
        si_ic(si)->rex = TICK_ETERNITY;
        si_oc(si)->wex = TICK_ETERNITY;
-quit:
        return;
 full:
        si->flags |= SI_FL_WAIT_ROOM;
index 37dad7ec0dae2586f43d6a3ea8a5174daed8aec3..2fdd94f6bd58d78780a3195a8bf084c7d36299fd 100644 (file)
@@ -394,6 +394,7 @@ struct appctx *stream_int_register_handler(struct stream_interface *si, struct a
                return NULL;
 
        si->flags |= SI_FL_WAIT_DATA;
+       appctx_wakeup(appctx);
        return si_appctx(si);
 }
 
@@ -1569,6 +1570,8 @@ static void stream_int_shutr_applet(struct stream_interface *si)
        ic->rex = TICK_ETERNITY;
        si->flags &= ~SI_FL_WAIT_ROOM;
 
+       /* Note: on shutr, we don't call the applet */
+
        if (si->state != SI_ST_EST && si->state != SI_ST_CON)
                return;
 
@@ -1581,10 +1584,6 @@ static void stream_int_shutr_applet(struct stream_interface *si)
                /* we want to immediately forward this close to the write side */
                return stream_int_shutw_applet(si);
        }
-
-       /* note that if the task exists, it must unregister itself once it runs */
-       if (!(si->flags & SI_FL_DONT_WAKE))
-               task_wakeup(si_task(si), TASK_WOKEN_IO);
 }
 
 /*
@@ -1606,6 +1605,9 @@ static void stream_int_shutw_applet(struct stream_interface *si)
        oc->wex = TICK_ETERNITY;
        si->flags &= ~SI_FL_WAIT_DATA;
 
+       /* on shutw we always wake the applet up */
+       appctx_wakeup(si_appctx(si));
+
        switch (si->state) {
        case SI_ST_EST:
                /* we have to shut before closing, otherwise some short messages
@@ -1633,10 +1635,6 @@ static void stream_int_shutw_applet(struct stream_interface *si)
                ic->rex = TICK_ETERNITY;
                si->exp = TICK_ETERNITY;
        }
-
-       /* note that if the task exists, it must unregister itself once it runs */
-       if (!(si->flags & SI_FL_DONT_WAKE))
-               task_wakeup(si_task(si), TASK_WOKEN_IO);
 }
 
 /* chk_rcv function for applets */
@@ -1650,17 +1648,14 @@ static void stream_int_chk_rcv_applet(struct stream_interface *si)
 
        if (unlikely(si->state != SI_ST_EST || (ic->flags & (CF_SHUTR|CF_DONT_READ))))
                return;
+       /* here we only wake the applet up if it was waiting for some room */
+       if (!(si->flags & SI_FL_WAIT_ROOM))
+               return;
 
-       if (!channel_may_recv(ic) || ic->pipe) {
-               /* stop reading */
-               si->flags |= SI_FL_WAIT_ROOM;
-       }
-       else {
+       if (channel_may_recv(ic) && !ic->pipe) {
                /* (re)start reading */
-               si->flags &= ~SI_FL_WAIT_ROOM;
-               if (!(si->flags & SI_FL_DONT_WAKE))
-                       task_wakeup(si_task(si), TASK_WOKEN_IO);
-       }
+               appctx_wakeup(si_appctx(si));
+        }
 }
 
 /* chk_snd function for applets */
@@ -1675,19 +1670,18 @@ static void stream_int_chk_snd_applet(struct stream_interface *si)
        if (unlikely(si->state != SI_ST_EST || (oc->flags & CF_SHUTW)))
                return;
 
-       if (!(si->flags & SI_FL_WAIT_DATA) ||        /* not waiting for data */
-           channel_is_empty(oc))           /* called with nothing to send ! */
+       /* we only wake the applet up if it was waiting for some data */
+
+       if (!(si->flags & SI_FL_WAIT_DATA))
                return;
 
-       /* Otherwise there are remaining data to be sent in the buffer,
-        * so we tell the handler.
-        */
-       si->flags &= ~SI_FL_WAIT_DATA;
        if (!tick_isset(oc->wex))
                oc->wex = tick_add_ifset(now_ms, oc->wto);
 
-       if (!(si->flags & SI_FL_DONT_WAKE))
-               task_wakeup(si_task(si), TASK_WOKEN_IO);
+       if (!channel_is_empty(oc)) {
+               /* (re)start sending */
+               appctx_wakeup(si_appctx(si));
+       }
 }
 
 /*