Summary
http_error_is_recoverable() and curl_error_is_recoverable() both start with a guard meant for "mid-stream on a non-seekable resource":
if (!c->seekable && c->request_start > 0 && !c->reconnect_streamed)
return 0;
Before the first reply has been probed, c->seekable is still 0 (meaning "unknown") and c->request_start == offset. So every open with offset > 0 is classified as "non-seekable, already streaming", and nothing is retried: not 429/503 from the default reconnect_on_http_error list, and not recoverable curl errors. The main victims are HLS EXT-X-BYTERANGE segments, where hls.c passes offset/end_offset, and applications resuming a download with offset.
Location
|
static int http_error_is_recoverable(CurlContext *c, long http_status) |
|
{ |
|
if (!c->reconnect_on_http_error || !http_status) |
|
return 0; |
|
if (!c->seekable && c->request_start > 0 && !c->reconnect_streamed) |
|
return 0; |
|
static int curl_error_is_recoverable(CurlContext *c, CURLcode code) |
|
{ |
|
if (!c->seekable && c->request_start > 0 && !c->reconnect_streamed) |
|
return 0; |
Reproduction
Server answers the first request with 503 + Retry-After: 1, then 206 (harness from #71):
$ t libcurl:http://127.0.0.1:18080/once503ra-b offset=1000
open: -1482175992 (Server returned 5XX Server Error reply)
The server sees a single request (Range: bytes=1000-), so no retry was attempted. The same resource with offset=0 does enter the retry path (which then fails for the reason in #71).
Suggested fix
Only apply the guard once the resource has actually been probed: if (c->probed && !c->seekable && c->request_start > 0 && !c->reconnect_streamed). Alternatively, key it on "bytes already delivered to the caller" rather than on request_start.
Summary
http_error_is_recoverable()andcurl_error_is_recoverable()both start with a guard meant for "mid-stream on a non-seekable resource":Before the first reply has been probed,
c->seekableis still 0 (meaning "unknown") andc->request_start == offset. So every open withoffset > 0is classified as "non-seekable, already streaming", and nothing is retried: not 429/503 from the defaultreconnect_on_http_errorlist, and not recoverable curl errors. The main victims are HLSEXT-X-BYTERANGEsegments, where hls.c passesoffset/end_offset, and applications resuming a download withoffset.Location
FFmpeg/libavformat/libcurl.c
Lines 194 to 199 in fe63f8f
FFmpeg/libavformat/libcurl.c
Lines 214 to 217 in fe63f8f
Reproduction
Server answers the first request with
503+Retry-After: 1, then206(harness from #71):The server sees a single request (
Range: bytes=1000-), so no retry was attempted. The same resource withoffset=0does enter the retry path (which then fails for the reason in #71).Suggested fix
Only apply the guard once the resource has actually been probed:
if (c->probed && !c->seekable && c->request_start > 0 && !c->reconnect_streamed). Alternatively, key it on "bytes already delivered to the caller" rather than onrequest_start.