mirror of
https://github.com/curl/curl.git
synced 2026-08-25 03:23:32 +03:00
transfer: do not use EXPIRE_NOW while blocked
- When a transfer sets `data->state.select_bits`, it is scheduled for rerun with EXPIRE_NOW. If such a transfer is blocked (due to PAUSE, for example), this will lead to a busy loop. - multi.c: check for transfer block - sendf.*: add Curl_xfer_is_blocked() - sendf.*: add client reader `is_paused()` callback - implement is_paused()` callback where needed Closes #13908
This commit is contained in:
parent
1424d507aa
commit
3841569ec8
10 changed files with 86 additions and 2 deletions
46
lib/sendf.c
46
lib/sendf.c
|
|
@ -606,6 +606,14 @@ CURLcode Curl_creader_def_unpause(struct Curl_easy *data,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
bool Curl_creader_def_is_paused(struct Curl_easy *data,
|
||||
struct Curl_creader *reader)
|
||||
{
|
||||
(void)data;
|
||||
(void)reader;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Curl_creader_def_done(struct Curl_easy *data,
|
||||
struct Curl_creader *reader, int premature)
|
||||
{
|
||||
|
|
@ -624,6 +632,7 @@ struct cr_in_ctx {
|
|||
BIT(seen_eos);
|
||||
BIT(errored);
|
||||
BIT(has_used_cb);
|
||||
BIT(is_paused);
|
||||
};
|
||||
|
||||
static CURLcode cr_in_init(struct Curl_easy *data, struct Curl_creader *reader)
|
||||
|
|
@ -646,6 +655,8 @@ static CURLcode cr_in_read(struct Curl_easy *data,
|
|||
struct cr_in_ctx *ctx = reader->ctx;
|
||||
size_t nread;
|
||||
|
||||
ctx->is_paused = FALSE;
|
||||
|
||||
/* Once we have errored, we will return the same error forever */
|
||||
if(ctx->errored) {
|
||||
*pnread = 0;
|
||||
|
|
@ -704,6 +715,7 @@ static CURLcode cr_in_read(struct Curl_easy *data,
|
|||
}
|
||||
/* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
|
||||
CURL_TRC_READ(data, "cr_in_read, callback returned CURL_READFUNC_PAUSE");
|
||||
ctx->is_paused = TRUE;
|
||||
data->req.keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
|
||||
*pnread = 0;
|
||||
*peos = FALSE;
|
||||
|
|
@ -866,6 +878,22 @@ static CURLcode cr_in_rewind(struct Curl_easy *data,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode cr_in_unpause(struct Curl_easy *data,
|
||||
struct Curl_creader *reader)
|
||||
{
|
||||
struct cr_in_ctx *ctx = reader->ctx;
|
||||
(void)data;
|
||||
ctx->is_paused = FALSE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static bool cr_in_is_paused(struct Curl_easy *data,
|
||||
struct Curl_creader *reader)
|
||||
{
|
||||
struct cr_in_ctx *ctx = reader->ctx;
|
||||
(void)data;
|
||||
return ctx->is_paused;
|
||||
}
|
||||
|
||||
static const struct Curl_crtype cr_in = {
|
||||
"cr-in",
|
||||
|
|
@ -876,7 +904,8 @@ static const struct Curl_crtype cr_in = {
|
|||
cr_in_total_length,
|
||||
cr_in_resume_from,
|
||||
cr_in_rewind,
|
||||
Curl_creader_def_unpause,
|
||||
cr_in_unpause,
|
||||
cr_in_is_paused,
|
||||
Curl_creader_def_done,
|
||||
sizeof(struct cr_in_ctx)
|
||||
};
|
||||
|
|
@ -1032,6 +1061,7 @@ static const struct Curl_crtype cr_lc = {
|
|||
Curl_creader_def_resume_from,
|
||||
Curl_creader_def_rewind,
|
||||
Curl_creader_def_unpause,
|
||||
Curl_creader_def_is_paused,
|
||||
Curl_creader_def_done,
|
||||
sizeof(struct cr_lc_ctx)
|
||||
};
|
||||
|
|
@ -1205,6 +1235,7 @@ static const struct Curl_crtype cr_null = {
|
|||
Curl_creader_def_resume_from,
|
||||
Curl_creader_def_rewind,
|
||||
Curl_creader_def_unpause,
|
||||
Curl_creader_def_is_paused,
|
||||
Curl_creader_def_done,
|
||||
sizeof(struct Curl_creader)
|
||||
};
|
||||
|
|
@ -1304,6 +1335,7 @@ static const struct Curl_crtype cr_buf = {
|
|||
cr_buf_resume_from,
|
||||
Curl_creader_def_rewind,
|
||||
Curl_creader_def_unpause,
|
||||
Curl_creader_def_is_paused,
|
||||
Curl_creader_def_done,
|
||||
sizeof(struct cr_buf_ctx)
|
||||
};
|
||||
|
|
@ -1366,6 +1398,18 @@ CURLcode Curl_creader_unpause(struct Curl_easy *data)
|
|||
return result;
|
||||
}
|
||||
|
||||
bool Curl_creader_is_paused(struct Curl_easy *data)
|
||||
{
|
||||
struct Curl_creader *reader = data->req.reader_stack;
|
||||
|
||||
while(reader) {
|
||||
if(reader->crt->is_paused(data, reader))
|
||||
return TRUE;
|
||||
reader = reader->next;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Curl_creader_done(struct Curl_easy *data, int premature)
|
||||
{
|
||||
struct Curl_creader *reader = data->req.reader_stack;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue