From f3f7aa5afff2c0be4a1a299a1a7d0a64558abc23 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Fri, 7 Dec 2018 21:46:27 +0300 Subject: [PATCH] http: fix connection retries when there more then one request for connection We should not attemp to establishe the connection if there is retry timer active, since otherwise there will be a bug. Imagine next situation: con = evhttp_connection_base_new() evhttp_connection_set_retries(con, 2) req = evhttp_request_new() evhttp_make_request(con, req, ...) # failed during connecting, and timer for 2 second scheduler (retry_ev) Then another request scheduled for this evcon: evhttp_make_request(con, req, ...) # got request from server, # and now it tries to read the response from the server # (req.kind == EVHTTP_RESPONSE) # # but at this point retry_ev scheduled, # and it schedules the connect again, # and after the connect will succeeed, it will pick request with # EVHTTP_RESPONSE for sending and this is completelly wrong and will # fail in evhttp_make_header_response() since there is no # "http_server" for this evcon This was a long standing issue, that I came across few years ago firstly, bad only now I had time to dig into it (but right now it was pretty simple, by limiting amount of CPU for the process and using rr for debug to go back and forth). --- http.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/http.c b/http.c index b49bc04c..3f2f40f4 100644 --- a/http.c +++ b/http.c @@ -1290,6 +1290,8 @@ evhttp_request_dispatch(struct evhttp_connection* evcon) if (req == NULL) return; + EVUTIL_ASSERT(req->kind == EVHTTP_REQUEST); + /* delete possible close detection events */ evhttp_connection_stop_detectclose(evcon); @@ -2644,6 +2646,10 @@ evhttp_make_request(struct evhttp_connection *evcon, TAILQ_INSERT_TAIL(&evcon->requests, req, next); + /* We do not want to conflict with retry_ev */ + if (evcon->retry_cnt) + return (0); + /* If the connection object is not connected; make it so */ if (!evhttp_connected(evcon)) { int res = evhttp_connection_connect_(evcon); @@ -2654,7 +2660,7 @@ evhttp_make_request(struct evhttp_connection *evcon, if (res != 0) TAILQ_REMOVE(&evcon->requests, req, next); - return res; + return (res); } /* -- 2.40.0