r16497@catbus: nickm | 2007-11-07 00:01:02 -0500

Resolve issue 1826588: make event_base_free() succeed even if there are pending non-INTERNAL events still in the base.  This can leak memory and fds if used injudiciously, but at least it no longer crashes.


svn:r490
This commit is contained in:
Nick Mathewson 2007-11-07 05:02:21 +00:00
parent 29420339dc
commit 206d433638
3 changed files with 36 additions and 3 deletions

View File

@ -40,4 +40,4 @@ Changes in current version:
o Remove support for the rtsig method: it hasn't compiled for a while, and nobody seems to miss it very much. Let us know if there's a good reason to put it back in.
o Rename the "class" field in evdns_server_request to dns_question_class, so that it won't break compilation under C++. Use a macro so that old code won't break. Mark the macro as deprecated.
o Fix DNS unit tests so that having a DNS server with broken IPv6 support is no longer cause for aborting the unit tests.
o Make event_base_free() succeed even if there are pending non-internal events on a base. This may still leak memory and fds, but at least it no longer crashes.

19
event.c
View File

@ -199,17 +199,32 @@ event_init(void)
void
event_base_free(struct event_base *base)
{
int i;
int i, n_deleted=0;
struct event *ev;
if (base == NULL && current_base)
base = current_base;
if (base == current_base)
if (base == current_base)
current_base = NULL;
/* XXX(niels) - check for internal events first */
assert(base);
/* Delete all non-internal events. */
for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) {
struct event *next = TAILQ_NEXT(ev, ev_next);
if (!(ev->ev_flags & EVLIST_INTERNAL)) {
event_del(ev);
++n_deleted;
}
ev = next;
}
if (n_deleted)
event_debug(("%s: %d events were still set in base",
__func__, n_deleted));
if (base->evsel->dealloc != NULL)
base->evsel->dealloc(base, base->evbase);
for (i=0; i < base->nactivequeues; ++i)
assert(TAILQ_EMPTY(base->activequeues[i]));
assert(min_heap_empty(&base->timeheap));

View File

@ -557,6 +557,22 @@ test_signal_switchbase(void)
}
#endif
void
test_free_active_base(void)
{
struct event_base *base1;
struct event ev1;
setup_test("Free active base: ");
base1 = event_init();
event_set(&ev1, pair[1], EV_READ, simple_read_cb, &ev1);
event_base_set(base1, &ev1);
event_add(&ev1, NULL);
/* event_del(&ev1); */
event_base_free(base1);
test_ok = 1;
cleanup_test();
}
void
test_loopexit(void)
{
@ -1063,6 +1079,8 @@ main (int argc, char **argv)
test_bufferevent();
test_free_active_base();
http_suite();
rpc_suite();