http: enable keepalive on TCP sockets

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>

Eric Wong committed Oct 12, 2013 at 22:29 UTC a15d069a19867b9c508ccfca5702f36448e829e8
1 file changed +22
http.c
+22
@@ -233,6 +233,24 @@ static int has_cert_password(void)
233 return 0;
234 }
235
236 +/* curl 7.25.0 has CURLOPT_TCP_KEEPALIVE, too, but we support older curl */
237 +static int sockopt_callback(void *client, curl_socket_t fd, curlsocktype type)
238 +{
239 + int ka = 1;
240 + int rc;
241 + socklen_t len = (socklen_t)sizeof(ka);
242 +
243 + if (type != CURLSOCKTYPE_IPCXN)
244 + return 0;
245 +
246 + rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka, len);
247 + if (rc < 0)
248 + warning("unable to set SO_KEEPALIVE on socket %s",
249 + strerror(errno));
250 +
251 + return 0; /* CURL_SOCKOPT_OK only exists since curl 7.21.5 */
252 +}
253 +
254 static CURL *get_curl_handle(void)
255 {
256 CURL *result = curl_easy_init();
@@ -298,6 +316,10 @@ static CURL *get_curl_handle(void)
316 if (curl_http_proxy)
317 curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
318
319 +#if LIBCURL_VERSION_NUM >= 0x071000
320 + curl_easy_setopt(result, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
321 +#endif
322 +
323 return result;
324 }
325