Summary
The only timeout libcurl.c configures is CURLOPT_CONNECTTIMEOUT_MS. It sets no CURLOPT_LOW_SPEED_LIMIT/CURLOPT_LOW_SPEED_TIME, and rw_timeout isn't mapped to anything curl knows about. So if a server or middlebox stops sending mid-body without closing the connection, the transfer stays open forever. CURLE_OPERATION_TIMEDOUT is in the recoverable list, but only a connect timeout can produce it, so the reconnect/retry machinery never runs for a stall.
Location
|
if (c->connect_timeout > 0) |
|
curl_easy_setopt(e, CURLOPT_CONNECTTIMEOUT_MS, |
|
(long)c->connect_timeout * 1000); |
|
switch (code) { |
|
case CURLE_RECV_ERROR: |
|
case CURLE_SEND_ERROR: |
|
case CURLE_PARTIAL_FILE: |
|
case CURLE_OPERATION_TIMEDOUT: |
|
case CURLE_GOT_NOTHING: |
|
case CURLE_HTTP2: |
|
case CURLE_HTTP2_STREAM: |
|
return 1; |
Reproduction
Server sends headers and 64 KiB of a 1 MiB body, then stalls without closing (harness from #71):
- Default options:
avio_read() blocks indefinitely (killed by timeout 8).
rw_timeout=2000000: avio gives up after ~2.7 s with a generic AVERROR(EIO) (total=65536 last=-5), and no reconnect is attempted (the server saw a single request).
Suggested fix
Map rw_timeout (or a dedicated option, e.g. stall_timeout, defaulting to something like 10–30 s) to CURLOPT_LOW_SPEED_LIMIT = 1 + CURLOPT_LOW_SPEED_TIME. A stall then surfaces as CURLE_OPERATION_TIMEDOUT in on_done() and goes through the existing retry path at the current logical_pos, with backoff and max_retries, instead of hanging or failing hard.
Summary
The only timeout libcurl.c configures is
CURLOPT_CONNECTTIMEOUT_MS. It sets noCURLOPT_LOW_SPEED_LIMIT/CURLOPT_LOW_SPEED_TIME, andrw_timeoutisn't mapped to anything curl knows about. So if a server or middlebox stops sending mid-body without closing the connection, the transfer stays open forever.CURLE_OPERATION_TIMEDOUTis in the recoverable list, but only a connect timeout can produce it, so the reconnect/retry machinery never runs for a stall.Location
FFmpeg/libavformat/libcurl.c
Lines 996 to 998 in fe63f8f
FFmpeg/libavformat/libcurl.c
Lines 219 to 227 in fe63f8f
Reproduction
Server sends headers and 64 KiB of a 1 MiB body, then stalls without closing (harness from #71):
avio_read()blocks indefinitely (killed bytimeout 8).rw_timeout=2000000: avio gives up after ~2.7 s with a genericAVERROR(EIO)(total=65536 last=-5), and no reconnect is attempted (the server saw a single request).Suggested fix
Map
rw_timeout(or a dedicated option, e.g.stall_timeout, defaulting to something like 10–30 s) toCURLOPT_LOW_SPEED_LIMIT = 1+CURLOPT_LOW_SPEED_TIME. A stall then surfaces asCURLE_OPERATION_TIMEDOUTinon_done()and goes through the existing retry path at the currentlogical_pos, with backoff andmax_retries, instead of hanging or failing hard.