git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/3] http.c: allow custom TCP keepalive behavior via config

From
Taylor Blau <me@ttaylorr.com>
Date
Mar 18, 2025, 22:21 UTC
Message-ID
<d84041580895a653648ee2370e21d7d2aa4fc4bb.1742336481.git.me@ttaylorr.com>
In-Reply-To
<cover.1742336481.git.me@ttaylorr.com>

curl supports a few options to control when and how often it should instruct the OS to send TCP keepalives, like KEEPIDLE, KEEPINTVL, and KEEPCNT. Until this point, there hasn't been a way for users to change what values are used for these options, forcing them to rely on curl's defaults.

But we do unconditionally enable TCP keepalives without giving users an ability to tweak any fine-grained parameters. Ordinarily this isn't a problem, particularly for users that have fast-enough connections, and/or are talking to a server that has generous or nonexistent thresholds for killing a connection it hasn't heard from in a while.

But it can present a problem when one or both of those assumptions fail. For instance, I can reliably get an in-progress clone to be killed from the remote end when cloning from some forges while using trickle to limit my clone's bandwidth.

For those users and others who wish to more finely tune the OS's keepalive behavior, expose configuration and environment variables which allow setting curl's KEEPIDLE, KEEPINTVL, and KEEPCNT options.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
 Documentation/config/http.adoc | 18 ++++++++++++++++++
 http.c                         | 31 ++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/Documentation/config/http.adoc b/Documentation/config/http.adoc
index 22a8803dea..67393282fa 100644
--- a/Documentation/config/http.adoc
+++ b/Documentation/config/http.adoc
@@ -296,6 +296,24 @@ http.lowSpeedLimit, http.lowSpeedTime::
 	Can be overridden by the `GIT_HTTP_LOW_SPEED_LIMIT` and
 	`GIT_HTTP_LOW_SPEED_TIME` environment variables.
 
+http.keepAliveIdle::
+	Specifies how long in seconds to wait on an idle connection
+	before sending TCP keepalive probes (if supported by the OS). If
+	unset, curl's default value is used. Can be overridden by the
+	`GIT_HTTP_KEEPALIVE_IDLE` environment variable.
+
+http.keepAliveInterval::
+	Specifies how long in seconds to wait between TCP keepalive
+	probes (if supported by the OS). If unset, curl's default value
+	is used. Can be overridden by the `GIT_HTTP_KEEPALIVE_INTERVAL`
+	environment variable.
+
+http.keepAliveCount::
+	Specifies how many TCP keepalive probes to send before giving up
+	and terminating the connection (if supported by the OS). If
+	unset, curl's default value is used. Can be overridden by the
+	`GIT_HTTP_KEEPALIVE_COUNT` environment variable.
+
 http.noEPSV::
 	A boolean which disables using of EPSV ftp command by curl.
 	This can be helpful with some "poor" ftp servers which don't
diff --git a/http.c b/http.c
index 526f9680f9..c13c7da530 100644
--- a/http.c
+++ b/http.c
@@ -104,6 +104,10 @@ static struct {
 };
 #endif
 
+static long curl_tcp_keepidle = -1;
+static long curl_tcp_keepintvl = -1;
+static long curl_tcp_keepcnt = -1;
+
 enum proactive_auth {
 	PROACTIVE_AUTH_NONE = 0,
 	PROACTIVE_AUTH_IF_CREDENTIALS,
@@ -557,6 +561,19 @@ static int http_options(const char *var, const char *value,
 		return 0;
 	}
 
+	if (!strcmp("http.keepaliveidle", var)) {
+		curl_tcp_keepidle = (long)git_config_int(var, value, ctx->kvi);
+		return 0;
+	}
+	if (!strcmp("http.keepaliveinterval", var)) {
+		curl_tcp_keepintvl = (long)git_config_int(var, value, ctx->kvi);
+		return 0;
+	}
+	if (!strcmp("http.keepalivecount", var)) {
+		curl_tcp_keepcnt = (long)git_config_int(var, value, ctx->kvi);
+		return 0;
+	}
+
 	/* Fall back on the default ones */
 	return git_default_config(var, value, ctx, data);
 }
@@ -704,7 +721,6 @@ static int has_proxy_cert_password(void)
 	return 1;
 }
 
-
 /* Return 1 if redactions have been made, 0 otherwise. */
 static int redact_sensitive_header(struct strbuf *header, size_t offset)
 {
@@ -1240,6 +1256,15 @@ static CURL *get_curl_handle(void)
 
 	curl_easy_setopt(result, CURLOPT_TCP_KEEPALIVE, 1);
 
+	if (curl_tcp_keepidle > -1)
+		curl_easy_setopt(result, CURLOPT_TCP_KEEPIDLE,
+				 curl_tcp_keepidle);
+	if (curl_tcp_keepintvl > -1)
+		curl_easy_setopt(result, CURLOPT_TCP_KEEPINTVL,
+				 curl_tcp_keepintvl);
+	if (curl_tcp_keepcnt > -1)
+		curl_easy_setopt(result, CURLOPT_TCP_KEEPCNT, curl_tcp_keepcnt);
+
 	return result;
 }
 
@@ -1367,6 +1392,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 			ssl_cert_password_required = 1;
 	}
 
+	set_long_from_env(&curl_tcp_keepidle, "GIT_TCP_KEEPIDLE");
+	set_long_from_env(&curl_tcp_keepintvl, "GIT_TCP_KEEPINTVL");
+	set_long_from_env(&curl_tcp_keepcnt, "GIT_TCP_KEEPCNT");
+
 	curl_default = get_curl_handle();
 }
 
-- 
2.49.0.3.gbb7a4a684c.dirty
Previous: Elijah NewrenNext: Patrick Steinhardt
Message 8 of 21 in “http: support fine-tuning curl's keepalive behavior”
  1. 0/3 http: support fine-tuning curl's keepalive behaviorTaylor Blau, Mar 18, 2025
  2. 1/3 http.c: introduce `set_long_from_env()` for convenienceTaylor Blau, Mar 18, 2025
  3. Elijah NewrenMar 19, 2025
  4. Patrick SteinhardtMar 19, 2025
  5. Taylor BlauMar 19, 2025
  6. 2/3 http.c: inline `set_curl_keepalive()`Taylor Blau, Mar 18, 2025
  7. Elijah NewrenMar 19, 2025
  8. 3/3 http.c: allow custom TCP keepalive behavior via configTaylor Blau, Mar 18, 2025
  9. Patrick SteinhardtMar 19, 2025
  10. Elijah NewrenMar 19, 2025
  11. Taylor BlauMar 19, 2025
  12. 0/4 http: support fine-tuning curl's keepalive behaviorTaylor Blau, Mar 19, 2025
  13. 1/4 http.c: remove unnecessary casts to longTaylor Blau, Mar 19, 2025
  14. 2/4 http.c: introduce `set_long_from_env()` for convenienceTaylor Blau, Mar 19, 2025
  15. Patrick SteinhardtMar 20, 2025
  16. Jeff KingApr 1, 2025
  17. 3/4 http.c: inline `set_curl_keepalive()`Taylor Blau, Mar 19, 2025
  18. Jeff KingApr 1, 2025
  19. 4/4 http.c: allow custom TCP keepalive behavior via configTaylor Blau, Mar 19, 2025
  20. Jeff KingApr 1, 2025
  21. Elijah NewrenMar 19, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.