summaryrefslogtreecommitdiff
path: root/http.c
diff options
context:
space:
mode:
authorTomash Brechko <tomash.brechko@gmail.com>2011-03-24 15:52:34 +0300
committerNick Mathewson <nickm@torproject.org>2011-04-04 14:44:34 -0400
commit218cf19743e3671924ec01edc9dc26be8b6f1ae8 (patch)
tree22c8c274c4b886a7c6b0d7497a5c21cf84efe816 /http.c
parent272823f8b0fb3c5f752ea5ff79b9b223b4d1b453 (diff)
downloadlibevent-218cf19743e3671924ec01edc9dc26be8b6f1ae8.tar.gz
Fix subtle recursion in evhttp_connection_cb_cleanup().
Diffstat (limited to 'http.c')
-rw-r--r--http.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/http.c b/http.c
index 1429462e..fa2b9cc3 100644
--- a/http.c
+++ b/http.c
@@ -1230,6 +1230,8 @@ evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
static void
evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
{
+ struct evcon_requestq requests;
+
if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
/* XXXX handle failure from evhttp_add_event */
@@ -1241,10 +1243,23 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
}
evhttp_connection_reset(evcon);
- /* for now, we just signal all requests by executing their callbacks */
+ /*
+ * User callback can do evhttp_make_request() on the same
+ * evcon so new request will be added to evcon->requests. To
+ * avoid freeing it prematurely we iterate over the copy of
+ * the queue.
+ */
+ TAILQ_INIT(&requests);
while (TAILQ_FIRST(&evcon->requests) != NULL) {
struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
TAILQ_REMOVE(&evcon->requests, request, next);
+ TAILQ_INSERT_TAIL(&requests, request, next);
+ }
+
+ /* for now, we just signal all requests by executing their callbacks */
+ while (TAILQ_FIRST(&requests) != NULL) {
+ struct evhttp_request *request = TAILQ_FIRST(&requests);
+ TAILQ_REMOVE(&requests, request, next);
request->evcon = NULL;
/* we might want to set an error here */