]> granicus.if.org Git - libevent/commitdiff
r16497@catbus: nickm | 2007-11-07 00:01:02 -0500
authorNick Mathewson <nickm@torproject.org>
Wed, 7 Nov 2007 05:02:21 +0000 (05:02 +0000)
committerNick Mathewson <nickm@torproject.org>
Wed, 7 Nov 2007 05:02:21 +0000 (05:02 +0000)
 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

ChangeLog
event.c
test/regress.c

index a78429eda06ea1c3599a485b018219913944f905..f772e6e1770748912a2fa9bbdd51be30b7b1353c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/event.c b/event.c
index 391d317ff970aa59a0eea88bce4d1b4f14f2f10c..fb94691bf92c8059a3ad5b96133ed5e00435b05e 100644 (file)
--- a/event.c
+++ b/event.c
@@ -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));
index 24ced27a213e79741af883e2549ea55edf91109b..e098f61c676b267420d27de1e09bb5bb55d0b1a0 100644 (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();