From 480883cf27b0dd938c50ab17ebf471d751307f7d Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Mon, 1 Jul 2024 14:56:27 +0200 Subject: [PATCH] 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 --- lib/cf-h2-proxy.c | 8 +++++++- lib/easy.c | 5 +++++ lib/multi.c | 8 ++++++-- lib/transfer.c | 8 -------- tests/unit/unit2600.c | 11 ++++++++++- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/cf-h2-proxy.c b/lib/cf-h2-proxy.c index b944200f7e..7613b7828d 100644 --- a/lib/cf-h2-proxy.c +++ b/lib/cf-h2-proxy.c @@ -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; diff --git a/lib/easy.c b/lib/easy.c index 22c5125399..75bf091bcb 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -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 diff --git a/lib/multi.c b/lib/multi.c index 1a0cdeadac..273c1771ec 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -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); } } diff --git a/lib/transfer.c b/lib/transfer.c index 3b554a81d9..4051f6743c 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -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 diff --git a/tests/unit/unit2600.c b/tests/unit/unit2600.c index 161e2cf19c..5c08d07d47 100644 --- a/tests/unit/unit2600.c +++ b/tests/unit/unit2600.c @@ -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, -- 2.47.3