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 :-) .
This commit is contained in:
Ondrej Zajicek 2008-12-18 23:26:08 +01:00
parent 35164c5017
commit b933281ed5
2 changed files with 5 additions and 2 deletions

View file

@ -125,13 +125,13 @@ ev_schedule(event *e)
int int
ev_run_list(event_list *l) ev_run_list(event_list *l)
{ {
node *n, *p; node *n;
list tmp_list; list tmp_list;
init_list(&tmp_list); init_list(&tmp_list);
add_tail_list(&tmp_list, l); add_tail_list(&tmp_list, l);
init_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); event *e = SKIP_BACK(event, n, n);
ev_run(e); ev_run(e);

View file

@ -37,6 +37,9 @@ typedef struct list { /* In fact two overlayed nodes */
n=(void *)((NODE (n))->next)) n=(void *)((NODE (n))->next))
#define WALK_LIST_DELSAFE(n,nxt,list) \ #define WALK_LIST_DELSAFE(n,nxt,list) \
for(n=HEAD(list); nxt=(void *)((NODE (n))->next); n=(void *) nxt) 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; \ #define WALK_LIST_BACKWARDS(n,list) for(n=TAIL(list);(NODE (n))->prev; \
n=(void *)((NODE (n))->prev)) n=(void *)((NODE (n))->prev))
#define WALK_LIST_BACKWARDS_DELSAFE(n,prv,list) \ #define WALK_LIST_BACKWARDS_DELSAFE(n,prv,list) \