http: enable keepalive on TCP sockets
authorEric Wong <normalperson@yhbt.net>
Sat, 12 Oct 2013 22:29:40 +0000 (22:29 +0000)
committerJonathan Nieder <jrnieder@gmail.com>
Mon, 14 Oct 2013 14:03:59 +0000 (07:03 -0700)
This is a follow up to commit e47a8583 (enable SO_KEEPALIVE for
connected TCP sockets, 2011-12-06).

Sockets may never receive notification of some link errors,
causing "git fetch" or similar processes to hang forever.
Enabling keepalive messages allows hung processes to error out
after a few minutes/hours depending on the keepalive settings of
the system.

I noticed this problem with some non-interactive cronjobs getting
hung when talking to HTTP servers.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
http.c
diff --git a/http.c b/http.c
index b2ae8de16db3abe2cad27249ae767f421aa6bb24..a2c1819e22f8fa961e9f6ae04b3f721fb10cbd79 100644 (file)
--- a/http.c
+++ b/http.c
@@ -233,6 +233,24 @@ static int has_cert_password(void)
                return 0;
 }
 
+/* curl 7.25.0 has CURLOPT_TCP_KEEPALIVE, too, but we support older curl */
+static int sockopt_callback(void *client, curl_socket_t fd, curlsocktype type)
+{
+       int ka = 1;
+       int rc;
+       socklen_t len = (socklen_t)sizeof(ka);
+
+       if (type != CURLSOCKTYPE_IPCXN)
+               return 0;
+
+       rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka, len);
+       if (rc < 0)
+               warning("unable to set SO_KEEPALIVE on socket %s",
+                       strerror(errno));
+
+       return 0; /* CURL_SOCKOPT_OK only exists since curl 7.21.5 */
+}
+
 static CURL *get_curl_handle(void)
 {
        CURL *result = curl_easy_init();
@@ -298,6 +316,10 @@ static CURL *get_curl_handle(void)
        if (curl_http_proxy)
                curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
 
+#if LIBCURL_VERSION_NUM >= 0x071000
+       curl_easy_setopt(result, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
+#endif
+
        return result;
 }