diff --git a/src/applet.c b/src/applet.c index cc467c49d..42d894d37 100644 --- a/src/applet.c +++ b/src/applet.c @@ -20,13 +20,29 @@ #include struct list applet_active_queue = LIST_HEAD_INIT(applet_active_queue); +struct list applet_run_queue = LIST_HEAD_INIT(applet_run_queue); void applet_run_active() { - struct appctx *curr, *back; + struct appctx *curr; struct stream_interface *si; - list_for_each_entry_safe(curr, back, &applet_active_queue, runq) { + if (LIST_ISEMPTY(&applet_active_queue)) + return; + + /* move active queue to run queue */ + applet_active_queue.n->p = &applet_run_queue; + applet_active_queue.p->n = &applet_run_queue; + + applet_run_queue = applet_active_queue; + LIST_INIT(&applet_active_queue); + + /* The list is only scanned from the head. This guarantees that if any + * applet removes another one, there is no side effect while walking + * through the list. + */ + while (!LIST_ISEMPTY(&applet_run_queue)) { + curr = LIST_ELEM(applet_run_queue.n, typeof(curr), runq); si = curr->owner; /* now we'll need a buffer */ @@ -46,5 +62,11 @@ void applet_run_active() curr->applet->fct(curr); si_applet_done(si); + + if (applet_run_queue.n == &curr->runq) { + /* curr was left in the list, move it back to the active list */ + LIST_DEL(&curr->runq); + LIST_ADDQ(&applet_active_queue, &curr->runq); + } } }