From d2af6e910fd8189bd14845df0846ceec736bcea4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Sep 2020 16:56:27 +0200 Subject: conncache: alloc "closure handle" on demand ... instead of always doing it beforehand, this now allocates it only in time of actual need. --- lib/conncache.c | 63 +++++++++++++++++++++++++++--------------------------- lib/conncache.h | 11 +++++++--- lib/multi.c | 23 ++++++++++---------- lib/share.c | 2 +- tests/data/test913 | 1 - 5 files changed, 52 insertions(+), 48 deletions(-) diff --git a/lib/conncache.c b/lib/conncache.c index c0e4d3e30..4f66f454f 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -112,21 +112,8 @@ static void free_bundle_hash_entry(void *freethis) int Curl_conncache_init(struct conncache *connc, int size) { - int rc; - - /* allocate a new easy handle to use when closing cached connections */ - connc->closure_handle = curl_easy_init(); - if(!connc->closure_handle) - return 1; /* bad */ - - rc = Curl_hash_init(&connc->hash, size, Curl_hash_str, - Curl_str_key_compare, free_bundle_hash_entry); - if(rc) - Curl_close(&connc->closure_handle); - else - connc->closure_handle->state.conn_cache = connc; - - return rc; + return Curl_hash_init(&connc->hash, size, Curl_hash_str, + Curl_str_key_compare, free_bundle_hash_entry); } void Curl_conncache_destroy(struct conncache *connc) @@ -531,38 +518,52 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) return conn_candidate; } -void Curl_conncache_close_all_connections(struct conncache *connc) +void Curl_conncache_close_all_connections(struct conncache *connc, + struct Curl_easy *data) { - struct connectdata *conn; char buffer[READBUFFER_MIN + 1]; - if(!connc->closure_handle) - return; - connc->closure_handle->state.buffer = buffer; - connc->closure_handle->set.buffer_size = READBUFFER_MIN; + struct Curl_easy *chandle; + struct connectdata *conn = conncache_find_first_connection(connc); + if(!conn) + return; /* no connection, we're done here */ + + /* No existing handle to use, allocate a new */ + if(!data && Curl_open(&chandle)) + return; /* BAD! */ + else if(data) + chandle = data; + else { + chandle->state.conn_cache = connc; + chandle->state.buffer = buffer; + chandle->set.buffer_size = READBUFFER_MIN; + if(connc->update_values) { + /* we have updated settings to use */ + chandle->set.timeout = connc->timeout; + chandle->set.server_response_timeout = connc->server_response_timeout; + chandle->set.no_signal = connc->no_signal; + } + } - conn = conncache_find_first_connection(connc); while(conn) { SIGPIPE_VARIABLE(pipe_st); - conn->data = connc->closure_handle; + conn->data = chandle; sigpipe_ignore(conn->data, &pipe_st); /* This will remove the connection from the cache */ connclose(conn, "kill all"); Curl_conncache_remove_conn(conn->data, conn, TRUE); - (void)Curl_disconnect(connc->closure_handle, conn, FALSE); + (void)Curl_disconnect(chandle, conn, FALSE); sigpipe_restore(&pipe_st); conn = conncache_find_first_connection(connc); } - connc->closure_handle->state.buffer = NULL; - if(connc->closure_handle) { + if(!data) { SIGPIPE_VARIABLE(pipe_st); - sigpipe_ignore(connc->closure_handle, &pipe_st); - - Curl_hostcache_clean(connc->closure_handle, - connc->closure_handle->dns.hostcache); - Curl_close(&connc->closure_handle); + chandle->state.buffer = NULL; + sigpipe_ignore(chandle, &pipe_st); + Curl_hostcache_clean(chandle, chandle->dns.hostcache); + Curl_close(&chandle); sigpipe_restore(&pipe_st); } } diff --git a/lib/conncache.h b/lib/conncache.h index c3e9ff51b..3e71043e9 100644 --- a/lib/conncache.h +++ b/lib/conncache.h @@ -34,8 +34,12 @@ struct conncache { size_t num_conn; long next_connection_id; struct curltime last_cleanup; - /* handle used for closing cached connections */ - struct Curl_easy *closure_handle; + + /* settings the "closure handle" wants */ + long timeout; + long server_response_timeout; + bool no_signal; + bool update_values; /* if these settings are set */ }; #define BUNDLE_NO_MULTIUSE -1 @@ -101,7 +105,8 @@ Curl_conncache_extract_bundle(struct Curl_easy *data, struct connectbundle *bundle); struct connectdata * Curl_conncache_extract_oldest(struct Curl_easy *data); -void Curl_conncache_close_all_connections(struct conncache *connc); +void Curl_conncache_close_all_connections(struct conncache *connc, + struct Curl_easy *data); void Curl_conncache_print(struct conncache *connc); #endif /* HEADER_CURL_CONNCACHE_H */ diff --git a/lib/multi.c b/lib/multi.c index 4cc7c5ae6..0f164edc4 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -519,11 +519,11 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, state somewhat we clone the timeouts from each added handle so that the closure handle always has the same timeouts as the most recently added easy handle. */ - data->state.conn_cache->closure_handle->set.timeout = data->set.timeout; - data->state.conn_cache->closure_handle->set.server_response_timeout = + data->state.conn_cache->timeout = data->set.timeout; + data->state.conn_cache->server_response_timeout = data->set.server_response_timeout; - data->state.conn_cache->closure_handle->set.no_signal = - data->set.no_signal; + data->state.conn_cache->no_signal = data->set.no_signal; + data->state.conn_cache->update_values = TRUE; CONNCACHE_UNLOCK(data); Curl_update_timer(multi); @@ -574,10 +574,8 @@ static CURLcode multi_done(struct Curl_easy *data, case CURLE_ABORTED_BY_CALLBACK: case CURLE_READ_ERROR: case CURLE_WRITE_ERROR: - /* When we're aborted due to a callback return code it basically have to - be counted as premature as there is trouble ahead if we don't. We have - many callbacks and protocols work differently, we could potentially do - this more fine-grained in the future. */ + case CURLE_OUT_OF_MEMORY: + case CURLE_SEND_ERROR: premature = TRUE; default: break; @@ -2602,8 +2600,12 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) multi->type = 0; /* not good anymore */ - /* Firsrt remove all remaining easy handles */ + /* First remove all remaining easy handles */ data = multi->easyp; + + /* Close all the connections in the connection cache */ + Curl_conncache_close_all_connections(&multi->conn_cache, data); + while(data) { nextdata = data->next; if(!data->state.done && data->conn) @@ -2628,9 +2630,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) data = nextdata; } - /* Close all the connections in the connection cache */ - Curl_conncache_close_all_connections(&multi->conn_cache); - Curl_hash_destroy(&multi->sockhash); Curl_conncache_destroy(&multi->conn_cache); Curl_llist_destroy(&multi->msglist, NULL); diff --git a/lib/share.c b/lib/share.c index 407ac3453..c03aa4143 100644 --- a/lib/share.c +++ b/lib/share.c @@ -197,7 +197,7 @@ curl_share_cleanup(struct Curl_share *share) return CURLSHE_IN_USE; } - Curl_conncache_close_all_connections(&share->conn_cache); + Curl_conncache_close_all_connections(&share->conn_cache, NULL); Curl_conncache_destroy(&share->conn_cache); Curl_hash_destroy(&share->hostcache); diff --git a/tests/data/test913 b/tests/data/test913 index d13a11ae8..782d029b8 100644 --- a/tests/data/test913 +++ b/tests/data/test913 @@ -44,7 +44,6 @@ smtp://%HOSTIP:%SMTPPORT/913 --mail-rcpt recipient@example.com --mail-from sende EHLO 913 MAIL FROM: SIZE=38 -QUIT -- cgit v1.2.1