multi: fix pollset during RESOLVING phase

- add a DEBUGASSERT for when a transfer's pollset should not be empty.
- move write unpausing from transfer loop into curl_easy_pause. This
  make sure that the url_updatesocket() finds the correct state when
  updating socket events.
- fix HTTP/2 proxy during connect phase to set sockets correctly
- fix test2600 to simulate a socket set
- move write unpausing from transfer loop into curl_easy_pause. This
  make sure that the url_updatesocket() finds the correct state when
  updating socket events.
- waiting for the resolver to deliver might not involve any sockets to
  wait for. Do not generate a warning.

Fixes #14047
Closes #14074
This commit is contained in:
Stefan Eissing 2024-07-01 14:56:27 +02:00 committed by Daniel Stenberg
parent 75763a3e88
commit 480883cf27
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 28 additions and 12 deletions

View File

@ -1230,7 +1230,13 @@ static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
bool want_recv, want_send;
Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
if(!cf->connected && ctx->h2) {
want_send = nghttp2_session_want_write(ctx->h2);
want_recv = nghttp2_session_want_read(ctx->h2);
}
else
Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
if(ctx->h2 && (want_recv || want_send)) {
bool c_exhaust, s_exhaust;

View File

@ -1143,6 +1143,11 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
goto out;
}
if(!(k->keepon & KEEP_RECV_PAUSE) && Curl_cwriter_is_paused(data)) {
Curl_conn_ev_data_pause(data, FALSE);
result = Curl_cwriter_unpause(data);
}
out:
if(!result && !data->state.done && keep_changed)
/* This transfer may have been moved in or out of the bundle, update the

View File

@ -1144,7 +1144,9 @@ static void multi_getsock(struct Curl_easy *data,
case MSTATE_RESOLVING:
Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
/* connection filters are not involved in this phase */
/* connection filters are not involved in this phase. It's ok if we get no
* sockets to wait for. Resolving can wake up from other sources. */
expect_sockets = FALSE;
break;
case MSTATE_CONNECTING:
@ -1195,8 +1197,10 @@ static void multi_getsock(struct Curl_easy *data,
break;
}
if(expect_sockets && !ps->num && !Curl_xfer_is_blocked(data)) {
if(expect_sockets && !ps->num &&
!(data->req.keepon & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) {
infof(data, "WARNING: no socket in pollset, transfer may stall!");
DEBUGASSERT(0);
}
}

View File

@ -414,14 +414,6 @@ CURLcode Curl_readwrite(struct Curl_easy *data)
int didwhat = 0;
int select_bits;
/* Check if client writes had been paused and can resume now. */
if(!(k->keepon & KEEP_RECV_PAUSE) && Curl_cwriter_is_paused(data)) {
Curl_conn_ev_data_pause(data, FALSE);
result = Curl_cwriter_unpause(data);
if(result)
goto out;
}
if(data->state.select_bits) {
if(select_bits_paused(data, data->state.select_bits)) {
/* leave the bits unchanged, so they'll tell us what to do when

View File

@ -152,6 +152,15 @@ static CURLcode cf_test_connect(struct Curl_cfilter *cf,
return CURLE_OK;
}
static void cf_test_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
/* just for testing, give one socket with events back */
(void)cf;
Curl_pollset_set(data, ps, 1, TRUE, TRUE);
}
static struct Curl_cftype cft_test = {
"TEST",
CF_TYPE_IP_CONNECT,
@ -161,7 +170,7 @@ static struct Curl_cftype cft_test = {
Curl_cf_def_close,
Curl_cf_def_shutdown,
Curl_cf_def_get_host,
Curl_cf_def_adjust_pollset,
cf_test_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,