From 2bb93466e5bc6a28e1f5c5671a511e0443c1073f Mon Sep 17 00:00:00 2001 From: Jay Satiro Date: Wed, 10 Jan 2024 03:53:23 -0500 Subject: [PATCH] easy: fix curl_easy_upkeep for shared connection caches - Predict which connection cache is or will be used by the easy handle and perform connection upkeep on that cache. This change allows curl_easy_upkeep to be effective on easy handles that are using a shared connection cache, either from a user created shared connection cache or a user created multi which has its own shared connection cache. Prior to this change curl_easy_upkeep would upkeep the connection cache for the easy handle only if that cache was from the multi owned by the easy handle (ie curl_easy_perform was previously called and there's a connection cache exclusive to the easy handle in data->multi_easy->conn_cache). Ref: https://curl.se/mail/lib-2024-01/0016.html Closes #xxxx --- lib/easy.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/easy.c b/lib/easy.c index 067b6d7b69f5fd..057325de6a9104 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -1346,13 +1346,31 @@ static CURLcode upkeep(struct conncache *conn_cache, void *data) */ CURLcode curl_easy_upkeep(struct Curl_easy *data) { + struct conncache *conn_cache; + /* Verify that we got an easy handle we can work with. */ if(!GOOD_EASY_HANDLE(data)) return CURLE_BAD_FUNCTION_ARGUMENT; - if(data->multi_easy) { + /* predict the connection cache that will next be used by the easy handle. + if the easy handle is currently in a multi then data->state.conn_cache + should point to the in-use cache. otherwise use the same logic that a + multi would use to assign it: if there's a user-specified shared cache + then use that, else use the multi's default shared cache. */ + DEBUGASSERT(!data->multi || data->state.conn_cache); + conn_cache = + data->state.conn_cache ? + data->state.conn_cache : + (data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT))) ? + &data->share->conn_cache : + data->multi ? + &data->multi->conn_cache : + data->multi_easy ? + &data->multi_easy->conn_cache : NULL; + + if(conn_cache) { /* Use the common function to keep connections alive. */ - return upkeep(&data->multi_easy->conn_cache, data); + return upkeep(conn_cache, data); } else { /* No connections, so just return success */