nickponline
nickponline

Reputation: 25914

Can you specify a timeout to git fetch?

I have some git commands scripted in python and occasionally git fetch can hang for hours if there is no connectivity. Is there a way to time it out and report a failure instead?

Upvotes: 2

Views: 6092

Answers (2)

user11509478
user11509478

Reputation:

I needed to change/set the timeout for this:

$ time git fetch
fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Failed to connect to git.xfce.org port 443: Connection timed out

real    2m11.684s
user    0m0.002s
sys 0m0.005s

(the 2min11sec probably depends on my sysctl settings)

and since this is stackoverflow, I had to patch git(instead of using the timeout command/wrapper) as follows to gain these two variants of specifying a timeout: ~/.gitconfig specified timeout(in seconds):

[http]
  connecttimeout = 10

so,

$ time git fetch
fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Connection timed out after 10009 milliseconds

real    0m10.031s
user    0m0.000s
sys 0m0.004s

and a way to override that ~/.gitconfig-specified timeout via env. var:

$ time GIT_HTTP_CONNECT_TIMEOUT=2 git fetch
fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Connection timed out after 2001 milliseconds

real    0m2.023s
user    0m0.000s
sys 0m0.004s

The patch in question(applied on latest git master commit 4c86140027f4a0d2caaa3ab4bd8bfc5ce3c11c8a Date: Wed Sep 18 11:55:13 2019 -0700) is:

diff --git a/http.c b/http.c
index 938b9e55af..c46737e48d 100644
--- a/http.c
+++ b/http.c
@@ -83,6 +83,7 @@ static const char *ssl_pinnedkey;
 static const char *ssl_cainfo;
 static long curl_low_speed_limit = -1;
 static long curl_low_speed_time = -1;
+static long curl_connecttimeout = -1; // in seconds, see man 3 CURLOPT_CONNECTTIMEOUT, default(for me, depending on sysctl setting probably!) is 2min10sec
 static int curl_ftp_no_epsv;
 static const char *curl_http_proxy;
 static const char *http_proxy_authmethod;
@@ -354,6 +355,10 @@ static int http_options(const char *var, const char *value, void *cb)
        curl_low_speed_time = (long)git_config_int(var, value);
        return 0;
    }
+   if (!strcmp("http.connecttimeout", var)) { // overriden by env var GIT_HTTP_CONNECT_TIMEOUT
+       curl_connecttimeout = (long)git_config_int(var, value);
+       return 0;
+   }

    if (!strcmp("http.noepsv", var)) {
        curl_ftp_no_epsv = git_config_bool(var, value);
@@ -935,6 +940,11 @@ static CURL *get_curl_handle(void)
        curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
                 curl_low_speed_time);
    }
+  if (curl_connecttimeout >= 0) {
+    //-1 or any negative means don't set a timeout which means (for me, depending on sysctl settings, no doubt) 2min10sec eg. 130sec and quits like: fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Failed to connect to git.xfce.org port 443: Connection timed out
+    //0 means set timeout to 0 which practically doesn't set a timeout and is the same as using a negative value! aka 2min10sec and quits like for -1 (see above)
+    curl_easy_setopt(result, CURLOPT_CONNECTTIMEOUT, curl_connecttimeout); //10L = timeout in 10 seconds instead of 2min10s eg. `git fetch` when: fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Failed to connect to git.xfce.org port 443: Connection timed out   --- real  2m10.809s  --- because git.xfce.org is down/not responding to ping! see $ man 3 CURLOPT_CONNECTTIMEOUT Setting a timeout quits like: fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Failed to connect to git.xfce.org port 443: Connection timed out
+  }

    curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20);
 #if LIBCURL_VERSION_NUM >= 0x071301
@@ -1061,6 +1071,7 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 {
    char *low_speed_limit;
    char *low_speed_time;
+   char *connecttimeout;
    char *normalized_url;
    struct urlmatch_config config = { STRING_LIST_INIT_DUP };

@@ -1151,6 +1162,9 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
    low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
    if (low_speed_time != NULL)
        curl_low_speed_time = strtol(low_speed_time, NULL, 10);
+  connecttimeout = getenv("GIT_HTTP_CONNECT_TIMEOUT"); // man 3 CURLOPT_CONNECTTIMEOUT ; can also be set in ~/.gitconfig as http.connecttimeout aka [http]\n\tconnecttimeout=10
+  if (connecttimeout != NULL)
+    curl_connecttimeout = strtol(connecttimeout, NULL, 10); //10 is base

    if (curl_ssl_verify == -1)
        curl_ssl_verify = 1;
@@ -1903,6 +1917,7 @@ static int http_request(const char *url,
    curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
    curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);

+
    ret = run_one_slot(slot, &results);

    if (options && options->content_type) {

Extras:
to override the ~/.gitconfig-set timeout and either set the timeout to 0 (which means no timeout because of how libcurl acts when CURLOPT_CONNECTTIMEOUT is set to 0) or simply not set any timeout(which currently means the same: no timeout because git doesn't touch/set CURLOPT_CONNECTTIMEOUT), either of these values will work: 0, or any negative value, ie.

$ time GIT_HTTP_CONNECT_TIMEOUT=0 git fetch
fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Failed to connect to git.xfce.org port 443: Connection timed out

real    2m11.255s
user    0m0.000s
sys 0m0.004s

$ time GIT_HTTP_CONNECT_TIMEOUT=-1 git fetch
fatal: unable to access 'https://git.xfce.org/xfce/xfce4-panel/': Failed to connect to git.xfce.org port 443: Connection timed out

real    2m8.710s
user    0m0.000s
sys 0m0.006s

Tested on archlinux:
local/curl 7.66.0-1
local/git 2.23.0.r256.g4c86140027-1

Upvotes: 2

nickponline
nickponline

Reputation: 25914

No you can't, you need to timeout the command using a wrapper.

Upvotes: 1

Related Questions