mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-12-14 22:21:01 +01:00
BUG/MEDIUM: apppet: Improve spinning loop detection with the new API
Conditions to detect the spinning loop for applets based on the new API are not accurrate. We cannot continue to check the channel's buffers state to know if an applet has made some progress. At least, we must also check the applet's buffers. After digging to find the right way to do, it was clear that the best is to use something similar to what is performed for the streams, namely, checking read and write events. And in fact, it is quite easy to do with the new API. So let's do so. This patch must be backported as far as 3.0.
This commit is contained in:
parent
dfe7fa9349
commit
54b7539d64
10
src/applet.c
10
src/applet.c
@ -898,6 +898,7 @@ struct task *task_process_applet(struct task *t, void *context, unsigned int sta
|
||||
struct appctx *app = context;
|
||||
struct stconn *sc;
|
||||
unsigned int rate;
|
||||
int did_send, did_recv;
|
||||
|
||||
TRACE_ENTER(APPLET_EV_PROCESS, app);
|
||||
|
||||
@ -925,6 +926,7 @@ struct task *task_process_applet(struct task *t, void *context, unsigned int sta
|
||||
sc = appctx_sc(app);
|
||||
|
||||
sc_applet_sync_send(sc);
|
||||
did_send = (sc_oc(sc)->flags & CF_WRITE_EVENT);
|
||||
|
||||
/* We always pretend the applet can't get and doesn't want to
|
||||
* put, it's up to it to change this if needed. This ensures
|
||||
@ -940,7 +942,7 @@ struct task *task_process_applet(struct task *t, void *context, unsigned int sta
|
||||
if (b_data(&app->outbuf) || se_fl_test(app->sedesc, SE_FL_MAY_FASTFWD_PROD))
|
||||
applet_have_more_data(app);
|
||||
|
||||
sc_applet_sync_recv(sc);
|
||||
did_recv = sc_applet_sync_recv(sc);
|
||||
|
||||
if (!se_fl_test(app->sedesc, SE_FL_WANT_ROOM)) {
|
||||
/* Handle EOI/EOS/ERROR outside of data transfer. But take care
|
||||
@ -966,11 +968,7 @@ struct task *task_process_applet(struct task *t, void *context, unsigned int sta
|
||||
}
|
||||
|
||||
/* measure the call rate and check for anomalies when too high */
|
||||
if (((b_size(sc_ib(sc)) && sc->flags & SC_FL_NEED_BUFF) || // asks for a buffer which is present
|
||||
(b_size(sc_ib(sc)) && !b_data(sc_ib(sc)) && sc->flags & SC_FL_NEED_ROOM) || // asks for room in an empty buffer
|
||||
(b_data(sc_ob(sc)) && sc_is_send_allowed(sc)) || // asks for data already present
|
||||
(!b_data(sc_ib(sc)) && b_data(sc_ob(sc)) && // didn't return anything ...
|
||||
(!(sc_oc(sc)->flags & CF_WRITE_EVENT) && (sc->flags & SC_FL_SHUT_WANTED))))) { // ... and left data pending after a shut
|
||||
if (!did_recv && !did_send) {
|
||||
rate = update_freq_ctr(&app->call_rate, 1);
|
||||
if (rate >= 100000 && app->call_rate.prev_ctr) // looped like this more than 100k times over last second
|
||||
stream_dump_and_crash(&app->obj_type, read_freq_ctr(&app->call_rate));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user