summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-12-10 12:46:16 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-12-10 17:02:04 +0100
commite43ad4b47442c99c95f76675a17e608610231871 (patch)
tree1d006818f5437e5b23a76923d201a4e2c48b9d16
parent439aa502115e2129db71d0b2d5441eb3790e2cd3 (diff)
downloadcurl-e43ad4b47442c99c95f76675a17e608610231871.tar.gz
multi: cleanup the socket hash when destroying itbagder/sockhash-destroy
Since each socket hash entry may themselves have a hash table in them, the destroying of the socket hash needs to make sure all the subhashes are also correctly destroyed to avoid leaking memory. Fixes #8129 Closes #8131
-rw-r--r--lib/multi.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/lib/multi.c b/lib/multi.c
index c34780f73..2bda97223 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -243,6 +243,26 @@ static void trhash_dtor(void *nada)
(void)nada;
}
+/*
+ * The sockhash has its own separate subhash in each entry that need to be
+ * safely destroyed first.
+ */
+static void sockhash_destroy(struct Curl_hash *h)
+{
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
+
+ DEBUGASSERT(h);
+ Curl_hash_start_iterate(h, &iter);
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr;
+ Curl_hash_destroy(&sh->transfers);
+ he = Curl_hash_next_element(&iter);
+ }
+ Curl_hash_destroy(h);
+}
+
/* make sure this socket is present in the hash for this handle */
static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
@@ -405,7 +425,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
error:
- Curl_hash_destroy(&multi->sockhash);
+ sockhash_destroy(&multi->sockhash);
Curl_hash_destroy(&multi->hostcache);
Curl_conncache_destroy(&multi->conn_cache);
Curl_llist_destroy(&multi->msglist, NULL);
@@ -554,7 +574,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
#if 0
/* Debug-function, used like this:
*
- * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
+ * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
*
* Enable the hash print function first by editing hash.c
*/
@@ -562,8 +582,8 @@ static void debug_print_sock_hash(void *p)
{
struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
- fprintf(stderr, " [easy %p/magic %x/socket %d]",
- (void *)sh->data, sh->data->magic, (int)sh->socket);
+ fprintf(stderr, " [readers %u][writers %u]",
+ sh->readers, sh->writers);
}
#endif
@@ -576,7 +596,8 @@ static CURLcode multi_done(struct Curl_easy *data,
struct connectdata *conn = data->conn;
unsigned int i;
- DEBUGF(infof(data, "multi_done"));
+ DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
+ (int)status, (int)premature, data->state.done));
if(data->state.done)
/* Stop if multi_done() has already been called */
@@ -2694,7 +2715,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
/* Close all the connections in the connection cache */
Curl_conncache_close_all_connections(&multi->conn_cache);
- Curl_hash_destroy(&multi->sockhash);
+ sockhash_destroy(&multi->sockhash);
Curl_conncache_destroy(&multi->conn_cache);
Curl_llist_destroy(&multi->msglist, NULL);
Curl_llist_destroy(&multi->pending, NULL);