curl: make --retry-delay and --retry-max-time accept decimal seconds

Like other time options already do.

Reported-by: Alice Lee Poetics
Fixes #18109
Closes #18111
This commit is contained in:
Daniel Stenberg 2025-07-31 00:02:25 +02:00
parent 3bfcfe82b9
commit 4d025fd912
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
5 changed files with 30 additions and 19 deletions

View 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.

View 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.

View 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 */

View 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);

View 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();