Hi, 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). At the end of this message, I've attached a gdb backtrace of an instance with the failed assertion and a patch that should revise the original solution to have an effect only when evhttp_connection_connect() fails. Kevin ***** begin gdb backtrace ***** #0 0xb7fe2430 in __kernel_vsyscall () #1 0xb7e8f651 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #2 0xb7e92a82 in *__GI_abort () at abort.c:92 #3 0x08090a8f in event_exit (errcode=-559030611) at log.c:79 #4 0x08090be9 in event_errx (eval=-559030611, fmt=0x80d3e78 "%s:%d: Assertion %s failed in %s") at log.c:136 #5 0x080894ec in evhttp_connection_fail (evcon=0x8572480, error=EVCON_HTTP_EOF) at http.c:689 #6 0x0808a766 in evhttp_error_cb (bufev=0x8572560, what=32, arg=0x8572480) at http.c:1327 #7 0x0808a7ce in evhttp_connection_cb (bufev=0x8572560, what=32, arg=0x8572480) at http.c:1352 #8 0x0807cde5 in _bufferevent_run_eventcb (bufev=0x8572560, what=32) at bufferevent.c:264 #9 0x0807fcce in bufferevent_socket_connect (bev=0x8572560, sa=0x8571bd0, socklen=16) at bufferevent_sock.c:420 #10 0x0807fd9a in bufferevent_connect_getaddrinfo_cb (result=0, ai=0x8571bb0, arg=0x8572560) at bufferevent_sock.c:453 #11 0x080872ac in evutil_getaddrinfo_async (dns_base=0x0, nodename=0x8572548 "72.14.204.141", servname=0xbfffe1c2 "80", hints_in=0xbfffe198, cb=0x807fcfe <bufferevent_connect_getaddrinfo_cb>, arg=0x8572560) at evutil.c:1396 #12 0x0807fed4 in bufferevent_socket_connect_hostname (bev=0x8572560, evdns_base=0x0, family=0, hostname=0x8572548 "72.14.204.141", port=80) at bufferevent_sock.c:489 #13 0x0808bee8 in evhttp_connection_connect (evcon=0x8572480) at http.c:2148 #14 0x0808c0a1 in evhttp_make_request (evcon=0x8572480, req=0x85715b0, type=EVHTTP_REQ_POST, uri=0x855b640 "/verify") at http.c:2199 ***** end gdb backtrace ***** ***** begin patch ***** diff --git a/libevent2/http.c b/libevent2/http.c index 06fe614..0797b5a 100644 --- a/libevent2/http.c +++ b/libevent2/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 ***** end patch ***** *********************************************************************** To unsubscribe, send an e-mail to majord...@freehaven.net with unsubscribe libevent-users in the body.