diff options
author | Tomash Brechko <tomash.brechko@gmail.com> | 2011-03-24 15:52:34 +0300 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2011-04-04 14:44:34 -0400 |
commit | 218cf19743e3671924ec01edc9dc26be8b6f1ae8 (patch) | |
tree | 22c8c274c4b886a7c6b0d7497a5c21cf84efe816 /http.c | |
parent | 272823f8b0fb3c5f752ea5ff79b9b223b4d1b453 (diff) | |
download | libevent-218cf19743e3671924ec01edc9dc26be8b6f1ae8.tar.gz |
Fix subtle recursion in evhttp_connection_cb_cleanup().
Diffstat (limited to 'http.c')
-rw-r--r-- | http.c | 17 |
1 files changed, 16 insertions, 1 deletions
@@ -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 */ |