mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-18 01:14:38 +00:00
BUG/MAJOR: applet: use a separate run queue to maintain list integrity
If an applet wakes up and causes the next one to sleep, the active list is corrupted and cannot be scanned anymore, as the process then loops over the next element. In order to avoid this problem, we move the active applet list to a run queue and reinit the active list. Only the first element of this queue is checked, and if the element is not removed, it is removed and requeued into the active list. Since we're using a distinct list, if an applet wants to requeue another applet into the active list, it properly gets added to the active list and not to the run queue. This stops the infinite loop issue that could be caused with Lua applets, and in any future configuration where two applets could be attached together.
This commit is contained in:
parent
64bca9d36a
commit
9994238adc
26
src/applet.c
26
src/applet.c
@ -20,13 +20,29 @@
|
||||
#include <proto/stream_interface.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user