From: Nick Mathewson Date: Thu, 23 Apr 2009 00:01:24 +0000 (+0000) Subject: Fix min_heap_erase when we remove an element from the middle of the heap. X-Git-Tag: release-2.0.3-alpha~284 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8b7a3b36763;p=libevent Fix min_heap_erase when we remove an element from the middle of the heap. Previously, we could lose the heap property when we removed an item whose parent was greater than the last element in the heap. We would replace the removed item with the last element, and consider shifting it down, but we wouldn't consider shifting it up. Patch from Marko Kreen. svn:r1226 --- diff --git a/ChangeLog b/ChangeLog index aea64512..a8f77200 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Changes in 2.0.2-alpha: o Fix a possible free(NULL) when freeing an event_base with no signals. o Add a flag to disable checking environment varibles when making an event_base o Disallow setting less than 1 priority. + o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen] Changes in 2.0.1-alpha: o free minheap on event_base_free(); from Christopher Layne diff --git a/minheap-internal.h b/minheap-internal.h index 6cd9c4aa..3b287043 100644 --- a/minheap-internal.h +++ b/minheap-internal.h @@ -88,7 +88,17 @@ int min_heap_erase(min_heap_t* s, struct event* e) { if(((unsigned int)-1) != e->min_heap_idx) { - min_heap_shift_down_(s, e->min_heap_idx, s->p[--s->n]); + struct event *last = s->p[--s->n]; + unsigned parent = (e->min_heap_idx - 1) / 2; + /* we replace e with the last element in the heap. We might need to + shift it upward if it is less than its parent, or downward if it is + greater than one or both its children. Since the children are known + to be less than the parent, it can't need to shift both up and + down. */ + if (e->min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last)) + min_heap_shift_up_(s, e->min_heap_idx, last); + else + min_heap_shift_down_(s, e->min_heap_idx, last); e->min_heap_idx = -1; return 0; }