]> granicus.if.org Git - libevent/commitdiff
Fix a race condition in the dns/bufferevent_connect_hostname test.
authorNick Mathewson <nickm@torproject.org>
Mon, 9 Jan 2012 21:44:53 +0000 (16:44 -0500)
committerNick Mathewson <nickm@torproject.org>
Mon, 9 Jan 2012 21:44:53 +0000 (16:44 -0500)
As originally written, the test would only pass if the accept()
callbacks for the evconnlistener were all invoked before the last of
the CONNECTED/ERROR callbacks for the connecting/resolving bufferevent
had its call to event_base_loopexit() complete.  But this was only
accidentally true in 2.0, and might not be true at all in 2.1 where
we schedule event_base_once() callbacks more aggressively.

Found by Sebastian Hahn.

test/regress_dns.c

index cd6369c76d35c7c33db7948459c32524fd9d95eb..5743dc7cd8cfa841bc47e990f19702a4ccbe28bf 100644 (file)
@@ -862,6 +862,7 @@ end:
 /* === Test for bufferevent_socket_connect_hostname */
 
 static int total_connected_or_failed = 0;
+static int total_n_accepted = 0;
 static struct event_base *be_connect_hostname_base = NULL;
 
 /* Implements a DNS server for the connect_hostname test and the
@@ -995,7 +996,11 @@ nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s,
 {
        int *p = arg;
        (*p)++;
+       ++total_n_accepted;
        /* don't do anything with the socket; let it close when we exit() */
+       if (total_n_accepted >= 3 && total_connected_or_failed >= 5)
+               event_base_loopexit(be_connect_hostname_base,
+                   NULL);
 }
 
 struct be_conn_hostname_result {
@@ -1015,14 +1020,14 @@ be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx)
 
                if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
                        int r;
-                       ++total_connected_or_failed;
-                       TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
                        if ((r = bufferevent_socket_get_dns_error(bev))) {
                                got->dnserr = r;
                                TT_BLATHER(("DNS error %d: %s", r,
                                           evutil_gai_strerror(r)));
-                       }
-                       if (total_connected_or_failed >= 5)
+                       }                       ++total_connected_or_failed;
+                       TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
+
+                       if (total_n_accepted >= 3 && total_connected_or_failed >= 5)
                                event_base_loopexit(be_connect_hostname_base,
                                    NULL);
                }