From: Christopher Faulet Date: Tue, 27 Apr 2021 15:08:10 +0000 (+0200) Subject: BUG/MINOR: applet: Notify the other side if data were consumed by an applet X-Git-Url: http://git.haproxy.org/?a=commitdiff_plain;h=90bd47f7431cf662941ee75a6f774efb707c4b24;p=haproxy-2.1.git BUG/MINOR: applet: Notify the other side if data were consumed by an applet If an applet consumed output data (the amount of output data has changed between before and after the call to the applet), the producer is notified. It means CF_WRITE_PARTIAL and CF_WROTE_DATA are set on the output channel and the opposite stream interface is notified some room was made in its input buffer. This way, it is no longer the applet responsibility to take care of it. However, it doesn't matter if the applet does the same. Said like that, it looks like an improvement not a bug. But it really fixes a bug in the lua, for HTTP applets. Indeed, applet:receive() and applet:getline() are buggy for HTTP applets. Data are consumed but the producer is not notified. It means if the payload is not fully received in one time, the applet may be blocked because the producer remains blocked (it is time dependent). This patch must be backported as far as 2.0 (only for the HTX part). (cherry picked from commit 1eedf9b4cb71da642399ae1efbfad2c1cdad6c33) Signed-off-by: Christopher Faulet (cherry picked from commit fffd9d8c7c7a1ff3a0b147ce28c4d960c48dc5d0) Signed-off-by: Christopher Faulet (cherry picked from commit 48da8402235bfd3464123a1f881e04174cda93f4) Signed-off-by: Christopher Faulet --- diff --git a/src/applet.c b/src/applet.c index 60c9e24..8ac7456 100644 --- a/src/applet.c +++ b/src/applet.c @@ -63,6 +63,7 @@ struct task *task_run_applet(struct task *t, void *context, unsigned short state struct appctx *app = context; struct stream_interface *si = app->owner; unsigned int rate; + size_t count; if (app->state & APPLET_WANT_DIE) { __appctx_free(app); @@ -85,8 +86,17 @@ struct task *task_run_applet(struct task *t, void *context, unsigned short state if (!si_alloc_ibuf(si, &app->buffer_wait)) si_rx_endp_more(si); + count = co_data(si_oc(si)); app->applet->fct(app); + /* now check if the applet has released some room and forgot to + * notify the other side about it. + */ + if (count != co_data(si_oc(si))) { + si_oc(si)->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA; + si_rx_room_rdy(si_opposite(si)); + } + /* measure the call rate and check for anomalies when too high */ rate = update_freq_ctr(&app->call_rate, 1); if (rate >= 100000 && app->call_rate.prev_ctr && // looped more than 100k times over last second