[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[Libevent-users] Bug: evhttp_make_request(), introduced in git commit 0d6622e
- To: libevent-users@xxxxxxxx
- Subject: [Libevent-users] Bug: evhttp_make_request(), introduced in git commit 0d6622e
- From: Kevin Ko <kevin.s.ko@xxxxxxxxx>
- Date: Tue, 10 May 2011 02:46:39 -0400
- Delivered-to: archiver@xxxxxxxx
- Delivered-to: libevent-users-outgoing@xxxxxxxx
- Delivered-to: libevent-users@xxxxxxxx
- Delivery-date: Tue, 10 May 2011 02:47:05 -0400
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:from:date:message-id:subject:to :content-type:content-transfer-encoding; bh=ptCuvOnhuGyUknupbzb5GRBOV03GOLQNWo/9vHBON14=; b=XsKqP/OSLahiQifSekZZdn280+w9NvspsOPbMowk9gGhP9Cbfi/HI7UQCgxLcILfvy heCrEyu0oEKyMs8Zd1WYNo8B2w4R4sZL/baY6BosGwagTKXXUD/HV0wE3a/xT8SnE/JR EXsTjDhGJ5V5iRKOIiEeEFhu0/o04EAArZqqY=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:from:date:message-id:subject:to:content-type :content-transfer-encoding; b=Bn1aqbT2xNVprcnUYdt4jmDQ+mbEWcYJFo6Uer2KO0ogDm03judY+axiOiOPwBOifm /h2ah4u/xgicjZSQBUVPVQhrkb3tcCI8byBwnqchUILdW7HqOZ05AqVJSOHNDOh+2w0Q ubfLanVomyy9FTZQdJHWZV4lcIq/07/5CzjMg=
- Reply-to: libevent-users@xxxxxxxxxxxxx
- Sender: owner-libevent-users@xxxxxxxxxxxxx
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 majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users in the body.