]> granicus.if.org Git - libevent/commitdiff
Fix a potentially very annoying evdns bug that we found in Tor.
authorNick Mathewson <nickm@torproject.org>
Fri, 22 May 2009 18:20:59 +0000 (18:20 +0000)
committerNick Mathewson <nickm@torproject.org>
Fri, 22 May 2009 18:20:59 +0000 (18:20 +0000)
Generally speaking, it way better to event_assign() an event when you
allocate it than to assign it before every time you event_add it: if
it is already event_add()ed, the assign will mess it up so that it
doesn't _look_ added, and event_add() will insert a second copy.
Later, event_del() will only delete the second copy.  Eventually, the
event_base will have a dangling pointer to freed memory.  Ouch!

svn:r1307

evdns.c

diff --git a/evdns.c b/evdns.c
index bcb55fcead930f41793ee0510788f2cdb869ae12..9562d46749ed50ff8b6fb47e6c888cb2e5a36140 100644 (file)
--- a/evdns.c
+++ b/evdns.c
@@ -559,8 +559,6 @@ nameserver_probe_failed(struct nameserver *const ns) {
                                                                                global_nameserver_timeouts_length - 1)];
        ns->failed_times++;
 
-       evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns);
-
        if (evtimer_add(&ns->timeout_event, (struct timeval *) timeout) < 0) {
          log(EVDNS_LOG_WARN,
              "Error from libevent when adding timer event for %s",
@@ -593,8 +591,6 @@ nameserver_failed(struct nameserver *const ns, const char *msg) {
        ns->state = 0;
        ns->failed_times = 1;
 
-       evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns);
-
        if (evtimer_add(&ns->timeout_event, (struct timeval *) &global_nameserver_timeouts[0]) < 0) {
                log(EVDNS_LOG_WARN,
                    "Error from libevent when adding timer event for %s",
@@ -2191,8 +2187,6 @@ evdns_request_transmit(struct evdns_request *req) {
                /* all ok */
                log(EVDNS_LOG_DEBUG,
                    "Setting timeout for request %lx", (unsigned long) req);
-               evtimer_assign(&req->timeout_event, req->base->event_base, evdns_request_timeout_callback, req);
-
                if (evtimer_add(&req->timeout_event, &req->base->global_timeout) < 0) {
                        log(EVDNS_LOG_WARN,
                      "Error from libevent when adding timer for request %lx",
@@ -2411,6 +2405,8 @@ _evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *addre
        memset(ns, 0, sizeof(struct nameserver));
        ns->base = base;
 
+       evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns);
+
        ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
        if (ns->socket < 0) { err = 1; goto out1; }
        evutil_make_socket_nonblocking(ns->socket);
@@ -2600,6 +2596,8 @@ request_new(struct evdns_base *base, int type, const char *name, int flags,
        memset(req, 0, sizeof(struct evdns_request));
        req->base = base;
 
+       evtimer_assign(&req->timeout_event, req->base->event_base, evdns_request_timeout_callback, req);
+
        if (base->global_randomize_case) {
                unsigned i;
                char randbits[(sizeof(namebuf)+7)/8];