summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2020-09-24 16:56:27 +0200
committerDaniel Stenberg <daniel@haxx.se>2020-09-24 19:32:04 +0200
commitd2af6e910fd8189bd14845df0846ceec736bcea4 (patch)
tree17683196eb721a0654d0074824e6eef51dbd7924
parent1397a7de6e312e019a3b339f855ba0a5cafa9127 (diff)
downloadcurl-bagder/conncache-closure.tar.gz
conncache: alloc "closure handle" on demandbagder/conncache-closure
... instead of always doing it beforehand, this now allocates it only in time of actual need.
-rw-r--r--lib/conncache.c63
-rw-r--r--lib/conncache.h11
-rw-r--r--lib/multi.c23
-rw-r--r--lib/share.c2
-rw-r--r--tests/data/test9131
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
<protocol>
EHLO 913
MAIL FROM:<sender@example.com> SIZE=38
-QUIT
</protocol>
</verify>
</testcase>