]> granicus.if.org Git - libevent/commitdiff
Fix failing assertion introducd in commit 0d6622e
authorKevin Ko <kevin.s.ko@gmail.com>
Sat, 21 May 2011 03:23:44 +0000 (23:23 -0400)
committerNick Mathewson <nickm@torproject.org>
Sat, 21 May 2011 03:23:44 +0000 (23:23 -0400)
Patch in question:
 - Fix the case when failed evhttp_make_request() leaved request in the queue.
 - http://levent.git.sourceforge.net/git/gitweb.cgi?p=levent/libevent;a=commit;h=0d6622e

The above patch introduces a failing assertion in
evhttp_connection_fail().  This happens because the patch defers the
assignment of the outstanding request to the evcon->requests list,
while evhttp_connection_fail() assumes that the request lies in the
list.

One scenario in which this can happen is when the request list is
empty and a connection is made to an unreachable host.  The assertion
will then fail after bufferevent_socket_connect() errors out (with
ENETUNREACH in my case).

http.c

diff --git a/http.c b/http.c
index 06fe6148a81abe8cd2019de52da2a53ec4460f95..c878a571c2b871d9a1a0bffc4457d31baa98cf7f 100644 (file)
--- a/http.c
+++ b/http.c
@@ -2194,21 +2194,21 @@ evhttp_make_request(struct evhttp_connection *evcon,
        req->evcon = evcon;
        EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
 
+       TAILQ_INSERT_TAIL(&evcon->requests, req, next);
+
        /* If the connection object is not connected; make it so */
        if (!evhttp_connected(evcon)) {
                int res = evhttp_connection_connect(evcon);
-               /*
-                * Enqueue the request only if we aren't going to
-                * return failure from evhttp_make_request().
-                */
-               if (res == 0)
-                       TAILQ_INSERT_TAIL(&evcon->requests, req, next);
+              /* evhttp_connection_fail(), which is called through
+               * evhttp_connection_connect(), assumes that req lies in
+               * evcon->requests.  Thus, enqueue the request in advance and r
+               * it in the error case. */
+              if (res != 0)
+                      TAILQ_REMOVE(&evcon->requests, req, next);
 
                return res;
        }
 
-       TAILQ_INSERT_TAIL(&evcon->requests, req, next);
-
        /*
         * If it's connected already and we are the first in the queue,
         * then we can dispatch this request immediately.  Otherwise, it