]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
curl: make --retry-delay and --retry-max-time accept decimal seconds
authorDaniel Stenberg <daniel@haxx.se>
Wed, 30 Jul 2025 22:02:25 +0000 (00:02 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 31 Jul 2025 06:55:58 +0000 (08:55 +0200)
Like other time options already do.

Reported-by: Alice Lee Poetics
Fixes #18109
Closes #18111

docs/cmdline-opts/retry-delay.md
docs/cmdline-opts/retry-max-time.md
src/tool_cfgable.h
src/tool_getparam.c
src/tool_operate.c

index fcee1767a465cf936e1afc6bdc217282583027c6..25ab1a660be8b02cd2b987108175bb696eb4f863 100644 (file)
@@ -9,6 +9,7 @@ Category: curl timeout
 Multi: single
 See-also:
   - retry
+  - retry-max-time
 Example:
   - --retry-delay 5 --retry 7 $URL
 ---
@@ -19,3 +20,9 @@ Make curl sleep this amount of time before each retry when a transfer has
 failed with a transient error (it changes the default backoff time algorithm
 between retries). This option is only interesting if --retry is also
 used. Setting this delay to zero makes curl use the default backoff time.
+
+By default, curl uses an exponentially increasing timeout between retries.
+
+Staring in curl 8.16.0, this option accepts a time as decimal number for parts
+of seconds. The decimal value needs to be provided using a dot (.) as decimal
+separator - not the local version even if it might be using another separator.
index e95a381a450302a4f77749efbd53abb146ec7580..654b00f3933d67c5a7f7257ccb9160509d745e93 100644 (file)
@@ -9,6 +9,7 @@ Category: curl timeout
 Multi: single
 See-also:
   - retry
+  - retry-delay
 Example:
   - --retry-max-time 30 --retry 10 $URL
 ---
@@ -16,8 +17,12 @@ Example:
 # `--retry-max-time`
 
 The retry timer is reset before the first transfer attempt. Retries are done
-as usual (see --retry) as long as the timer has not reached this given
-limit. Notice that if the timer has not reached the limit, the request is
-made and while performing, it may take longer than this given time period. To
-limit a single request's maximum time, use --max-time. Set this option to zero
-to not timeout retries.
+as usual (see --retry) as long as the timer has not reached this given limit.
+Notice that if the timer has not reached the limit, the request is made and
+while performing, it may take longer than this given time period. To limit a
+single request's maximum time, use --max-time. Set this option to zero to not
+timeout retries.
+
+Staring in curl 8.16.0, this option accepts a time as decimal number for parts
+of seconds. The decimal value needs to be provided using a dot (.) as decimal
+separator - not the local version even if it might be using another separator.
index 80411f2cd85046303c1b59e2ef3d3888a01f54ab..d23902885e4d92ee1579a76015c8098408f60c87 100644 (file)
@@ -212,8 +212,8 @@ struct OperationConfig {
   long httpversion;
   unsigned long socks5_auth;/* auth bitmask for socks5 proxies */
   long req_retry;           /* number of retries */
-  long retry_delay;         /* delay between retries (in seconds) */
-  long retry_maxtime;       /* maximum time to keep retrying */
+  long retry_delay_ms;      /* delay between retries (in milliseconds) */
+  long retry_maxtime_ms;    /* maximum time to keep retrying */
 
   unsigned long mime_options; /* Mime option flags. */
   long tftp_blksize;        /* TFTP BLKSIZE option */
index ad76c8d280e266589b0713c2c5383d670a2038a2..4540a5913649419284b6bbe918a2904e1dafce03 100644 (file)
@@ -2344,10 +2344,10 @@ static ParameterError opt_filestring(struct OperationConfig *config,
     err = str2unum(&config->req_retry, nextarg);
     break;
   case C_RETRY_DELAY: /* --retry-delay */
-    err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
+    err = secs2ms(&config->retry_delay_ms, nextarg);
     break;
   case C_RETRY_MAX_TIME: /* --retry-max-time */
-    err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
+    err = secs2ms(&config->retry_maxtime_ms, nextarg);
     break;
   case C_FTP_ACCOUNT: /* --ftp-account */
     err = getstr(&config->ftp_account, nextarg, DENY_BLANK);
index 17e1c1cf966361de99e01a3a94f6656435635f58..7e09528844c135c73ec84dc60723b6730234936d 100644 (file)
@@ -469,12 +469,11 @@ static CURLcode retrycheck(struct OperationConfig *config,
         /* if adding retry_after seconds to the process would exceed the
            maximum time allowed for retrying, then exit the retries right
            away */
-        if(config->retry_maxtime) {
-          curl_off_t seconds = curlx_timediff(curlx_now(),
-                                              per->retrystart)/1000;
+        if(config->retry_maxtime_ms) {
+          timediff_t ms = curlx_timediff(curlx_now(), per->retrystart);
 
-          if((CURL_OFF_T_MAX - retry_after < seconds) ||
-             (seconds + retry_after > config->retry_maxtime)) {
+          if((CURL_OFF_T_MAX - sleeptime < ms) ||
+             (ms + sleeptime > config->retry_maxtime_ms)) {
             warnf(config->global, "The Retry-After: time would "
                   "make this command line exceed the maximum allowed time "
                   "for retries.");
@@ -493,7 +492,7 @@ static CURLcode retrycheck(struct OperationConfig *config,
           (per->retry_remaining > 1 ? "ies" : "y"));
 
     per->retry_remaining--;
-    if(!config->retry_delay) {
+    if(!config->retry_delay_ms) {
       per->retry_sleep *= 2;
       if(per->retry_sleep > RETRY_SLEEP_MAX)
         per->retry_sleep = RETRY_SLEEP_MAX;
@@ -659,9 +658,9 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
   /* if retry-max-time is non-zero, make sure we have not exceeded the
      time */
   if(per->retry_remaining &&
-     (!config->retry_maxtime ||
+     (!config->retry_maxtime_ms ||
       (curlx_timediff(curlx_now(), per->retrystart) <
-       config->retry_maxtime*1000L)) ) {
+       config->retry_maxtime_ms)) ) {
     result = retrycheck(config, per, result, retryp, delay);
     if(!result && *retryp)
       return CURLE_OK; /* retry! */
@@ -1366,8 +1365,8 @@ static CURLcode single_transfer(struct OperationConfig *config,
         return result;
 
       /* initialize retry vars for loop below */
-      per->retry_sleep_default = (config->retry_delay) ?
-        config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
+      per->retry_sleep_default = config->retry_delay_ms ?
+        config->retry_delay_ms : RETRY_SLEEP_DEFAULT; /* ms */
       per->retry_remaining = config->req_retry;
       per->retry_sleep = per->retry_sleep_default; /* ms */
       per->retrystart = curlx_now();