From: "Shawn O. Pearce" <spea...@spearce.org>

When libcurl fails to connect to an SSL server always retry the
request once. Since the connection failed before the HTTP headers
can be sent, no data has exchanged hands, so the remote side has
not learned of the request and will not perform it twice.

In the wild we have seen git-remote-https fail to connect to
some load-balanced SSL servers sporadically, while modern popular
browsers (e.g. Firefox and Chromium) have no trouble with the same
server pool.

Lets assume the site operators (Hi Google!) have a clue and are
doing everything they already can to ensure secure, successful
SSL connections from a wide range of HTTP clients. Implementing a
single level of retry in the client can make it more robust against
transient failure modes.
---
 http.c        | 19 ++++++++++++-------
 remote-curl.c |  2 ++
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/http.c b/http.c
index 345c171..953f2e6 100644
--- a/http.c
+++ b/http.c
@@ -784,7 +784,7 @@ static int http_request(const char *url, void *result, int 
target, int options)
        struct slot_results results;
        struct curl_slist *headers = NULL;
        struct strbuf buf = STRBUF_INIT;
-       int ret;
+       int ret, attempts;
 
        slot = get_active_slot();
        slot->results = &results;
@@ -820,12 +820,17 @@ static int http_request(const char *url, void *result, 
int target, int options)
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
 
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               ret = handle_curl_result(slot);
-       } else {
-               error("Unable to start HTTP request for %s", url);
-               ret = HTTP_START_FAILED;
+       for (attempts = 0; attempts < 2; attempts++) {
+               if (start_active_slot(slot)) {
+                       run_active_slot(slot);
+                       if (slot->results->curl_result == 
CURLE_SSL_CONNECT_ERROR)
+                               continue;
+                       ret = handle_curl_result(slot);
+               } else {
+                       error("Unable to start HTTP request for %s", url);
+                       ret = HTTP_START_FAILED;
+               }
+               break;
        }
 
        curl_slist_free_all(headers);
diff --git a/remote-curl.c b/remote-curl.c
index a269608..04a379c 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -353,6 +353,8 @@ static int run_slot(struct active_request_slot *slot)
 
        slot->results = &results;
        slot->curl_result = curl_easy_perform(slot->curl);
+       if (slot->curl_result == CURLE_SSL_CONNECT_ERROR)
+               slot->curl_result = curl_easy_perform(slot->curl);
        finish_active_slot(slot);
 
        err = handle_curl_result(slot);
-- 
1.7.12.1.590.g4bb1bc4

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to