diff options
author | Daniel Stenberg <daniel@haxx.se> | 2020-04-27 00:33:21 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2020-04-30 14:27:54 +0200 |
commit | c06902713998d68202c5a764de910ba8d0e8f54d (patch) | |
tree | bc7f53131c6b294af2b0475ed83349d0dcee8a3d /lib/conncache.c | |
parent | 9a8fa076bff31b55b6d12c0c6da7448ec4ecdf67 (diff) | |
download | curl-c06902713998d68202c5a764de910ba8d0e8f54d.tar.gz |
conncache: various concept cleanups
More connection cache accesses are protected by locks.
CONNCACHE_* is a beter prefix for the connection cache lock macros.
Curl_attach_connnection: now called as soon as there's a connection
struct available and before the connection is added to the connection
cache.
Curl_disconnect: now assumes that the connection is already removed from
the connection cache.
Ref: #4915
Closes #5009
Diffstat (limited to 'lib/conncache.c')
-rw-r--r-- | lib/conncache.c | 87 |
1 files changed, 40 insertions, 47 deletions
diff --git a/lib/conncache.c b/lib/conncache.c index cbd3bb1bb..95fcea6f3 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -49,53 +49,51 @@ static void conn_llist_dtor(void *user, void *element) conn->bundle = NULL; } -static CURLcode bundle_create(struct Curl_easy *data, - struct connectbundle **cb_ptr) +static CURLcode bundle_create(struct connectbundle **bundlep) { - (void)data; - DEBUGASSERT(*cb_ptr == NULL); - *cb_ptr = malloc(sizeof(struct connectbundle)); - if(!*cb_ptr) + DEBUGASSERT(*bundlep == NULL); + *bundlep = malloc(sizeof(struct connectbundle)); + if(!*bundlep) return CURLE_OUT_OF_MEMORY; - (*cb_ptr)->num_connections = 0; - (*cb_ptr)->multiuse = BUNDLE_UNKNOWN; + (*bundlep)->num_connections = 0; + (*bundlep)->multiuse = BUNDLE_UNKNOWN; - Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor); + Curl_llist_init(&(*bundlep)->conn_list, (curl_llist_dtor) conn_llist_dtor); return CURLE_OK; } -static void bundle_destroy(struct connectbundle *cb_ptr) +static void bundle_destroy(struct connectbundle *bundle) { - if(!cb_ptr) + if(!bundle) return; - Curl_llist_destroy(&cb_ptr->conn_list, NULL); + Curl_llist_destroy(&bundle->conn_list, NULL); - free(cb_ptr); + free(bundle); } /* Add a connection to a bundle */ -static void bundle_add_conn(struct connectbundle *cb_ptr, +static void bundle_add_conn(struct connectbundle *bundle, struct connectdata *conn) { - Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn, + Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn, &conn->bundle_node); - conn->bundle = cb_ptr; - cb_ptr->num_connections++; + conn->bundle = bundle; + bundle->num_connections++; } /* Remove a connection from a bundle */ -static int bundle_remove_conn(struct connectbundle *cb_ptr, +static int bundle_remove_conn(struct connectbundle *bundle, struct connectdata *conn) { struct curl_llist_element *curr; - curr = cb_ptr->conn_list.head; + curr = bundle->conn_list.head; while(curr) { if(curr->ptr == conn) { - Curl_llist_remove(&cb_ptr->conn_list, curr, NULL); - cb_ptr->num_connections--; + Curl_llist_remove(&bundle->conn_list, curr, NULL); + bundle->num_connections--; conn->bundle = NULL; return 1; /* we removed a handle */ } @@ -162,20 +160,15 @@ static void hashkey(struct connectdata *conn, char *buf, msnprintf(buf, len, "%ld%s", port, hostname); } -void Curl_conncache_unlock(struct Curl_easy *data) -{ - CONN_UNLOCK(data); -} - /* Returns number of connections currently held in the connection cache. Locks/unlocks the cache itself! */ size_t Curl_conncache_size(struct Curl_easy *data) { size_t num; - CONN_LOCK(data); + CONNCACHE_LOCK(data); num = data->state.conn_cache->num_conn; - CONN_UNLOCK(data); + CONNCACHE_UNLOCK(data); return num; } @@ -188,7 +181,7 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, const char **hostp) { struct connectbundle *bundle = NULL; - CONN_LOCK(conn->data); + CONNCACHE_LOCK(conn->data); if(connc) { char key[HASHKEY_SIZE]; hashkey(conn, key, sizeof(key), hostp); @@ -235,8 +228,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, struct connectdata *conn) { CURLcode result = CURLE_OK; - struct connectbundle *bundle; - struct connectbundle *new_bundle = NULL; + struct connectbundle *bundle = NULL; struct Curl_easy *data = conn->data; /* *find_bundle() locks the connection cache */ @@ -245,20 +237,19 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, int rc; char key[HASHKEY_SIZE]; - result = bundle_create(data, &new_bundle); + result = bundle_create(&bundle); if(result) { goto unlock; } hashkey(conn, key, sizeof(key), NULL); - rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); + rc = conncache_add_bundle(data->state.conn_cache, key, bundle); if(!rc) { - bundle_destroy(new_bundle); + bundle_destroy(bundle); result = CURLE_OUT_OF_MEMORY; goto unlock; } - bundle = new_bundle; } bundle_add_conn(bundle, conn); @@ -270,15 +261,17 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, conn->connection_id, connc->num_conn)); unlock: - CONN_UNLOCK(data); + CONNCACHE_UNLOCK(data); return result; } /* - * Removes the connectdata object from the connection cache *and* clears the - * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument - * depending on if the parent function already holds the lock or not. + * Removes the connectdata object from the connection cache, but does *not* + * clear the conn->data association. The transfer still owns this connection. + * + * Pass TRUE/FALSE in the 'lock' argument depending on if the parent function + * already holds the lock or not. */ void Curl_conncache_remove_conn(struct Curl_easy *data, struct connectdata *conn, bool lock) @@ -290,7 +283,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data, due to a failed connection attempt, before being added to a bundle */ if(bundle) { if(lock) { - CONN_LOCK(data); + CONNCACHE_LOCK(data); } bundle_remove_conn(bundle, conn); if(bundle->num_connections == 0) @@ -301,9 +294,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data, DEBUGF(infof(data, "The cache now contains %zu members\n", connc->num_conn)); } - conn->data = NULL; /* clear the association */ if(lock) { - CONN_UNLOCK(data); + CONNCACHE_UNLOCK(data); } } } @@ -332,7 +324,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data, if(!connc) return FALSE; - CONN_LOCK(data); + CONNCACHE_LOCK(data); Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); @@ -350,12 +342,12 @@ bool Curl_conncache_foreach(struct Curl_easy *data, curr = curr->next; if(1 == func(conn, param)) { - CONN_UNLOCK(data); + CONNCACHE_UNLOCK(data); return TRUE; } } } - CONN_UNLOCK(data); + CONNCACHE_UNLOCK(data); return FALSE; } @@ -494,7 +486,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) now = Curl_now(); - CONN_LOCK(data); + CONNCACHE_LOCK(data); Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); @@ -531,7 +523,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) connc->num_conn)); conn_candidate->data = data; /* associate! */ } - CONN_UNLOCK(data); + CONNCACHE_UNLOCK(data); return conn_candidate; } @@ -548,6 +540,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc) 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); sigpipe_restore(&pipe_st); |