From: Ondrej Zajicek Date: Thu, 18 Dec 2008 22:26:08 +0000 (+0100) Subject: Fixes nasty bug in event processing. X-Git-Tag: v1.2.0~165 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b933281ed5efb9ad9375c3ea41ee2412b9f89c15;p=thirdparty%2Fbird.git Fixes nasty bug in event processing. WALK_LIST_DELSAFE (in ev_run_list) is not safe with regard to deletion of next node. When some events are rescheduled during event execution, it may lead to deletion of next node and some events are skipped. Such skipped nodes remain in temporary list on stack and the last of them contains 'next' pointer to stack area. When this event is later scheduled, it damages stack area trying to remove it from the list, which leads to random crashes with funny backtraces :-) . --- diff --git a/lib/event.c b/lib/event.c index 9b5870d33..55a9c4872 100644 --- a/lib/event.c +++ b/lib/event.c @@ -125,13 +125,13 @@ ev_schedule(event *e) int ev_run_list(event_list *l) { - node *n, *p; + node *n; list tmp_list; init_list(&tmp_list); add_tail_list(&tmp_list, l); init_list(l); - WALK_LIST_DELSAFE(n, p, tmp_list) + WALK_LIST_FIRST(n, tmp_list) { event *e = SKIP_BACK(event, n, n); ev_run(e); diff --git a/lib/lists.h b/lib/lists.h index 5b36ec83e..342dfd62b 100644 --- a/lib/lists.h +++ b/lib/lists.h @@ -37,6 +37,9 @@ typedef struct list { /* In fact two overlayed nodes */ n=(void *)((NODE (n))->next)) #define WALK_LIST_DELSAFE(n,nxt,list) \ for(n=HEAD(list); nxt=(void *)((NODE (n))->next); n=(void *) nxt) +/* WALK_LIST_FIRST supposes that called code removes each processed node */ +#define WALK_LIST_FIRST(n,list) \ + while(n=HEAD(list), (NODE (n))->next) #define WALK_LIST_BACKWARDS(n,list) for(n=TAIL(list);(NODE (n))->prev; \ n=(void *)((NODE (n))->prev)) #define WALK_LIST_BACKWARDS_DELSAFE(n,prv,list) \