]> granicus.if.org Git - curl/commitdiff
disconnect: separate connections and easy handles better
authorDaniel Stenberg <daniel@haxx.se>
Thu, 20 Dec 2018 15:39:02 +0000 (16:39 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 22 Dec 2018 17:14:50 +0000 (18:14 +0100)
Do not assume/store assocation between a given easy handle and the
connection if it can be avoided.

Long-term, the 'conn->data' pointer should probably be removed as it is a
little too error-prone. Still used very widely though.

Reported-by: masbug on github
Fixes #3391
Closes #3400

lib/conncache.c
lib/conncache.h
lib/multi.c
lib/url.c

index 08e9042a6fb08fe8324fd04dd2528227370da1ac..080441854c361b9ce5e6b711a85cb09389148e56 100644 (file)
@@ -302,9 +302,14 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
   return result;
 }
 
-void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
+/*
+ * 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.
+ */
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn, bool lock)
 {
-  struct Curl_easy *data = conn->data;
   struct connectbundle *bundle = conn->bundle;
   struct conncache *connc = data->state.conn_cache;
 
@@ -323,6 +328,7 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
       DEBUGF(infof(data, "The cache now contains %zu members\n",
                    connc->num_conn));
     }
+    conn->data = NULL; /* clear the association */
     if(lock) {
       CONN_UNLOCK(data);
     }
index eedd7a800ef8a730028b3020f2bbb9db75684db8..81566dcd345b41834645baab687f8a125b0b5992 100644 (file)
@@ -64,7 +64,8 @@ size_t Curl_conncache_bundle_size(struct connectdata *conn);
 bool Curl_conncache_return_conn(struct connectdata *conn);
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                  struct connectdata *conn) WARN_UNUSED_RESULT;
-void Curl_conncache_remove_conn(struct connectdata *conn,
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn,
                                 bool lock);
 bool Curl_conncache_foreach(struct Curl_easy *data,
                             struct conncache *connc,
index 56b3faf2fadabb9b277dda01cc74acfc1954dd24..d8121250c996dcaf062e8de28aeb80c6dc353545 100644 (file)
@@ -761,10 +761,8 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
                                 vanish with this handle */
 
   /* Remove the association between the connection and the handle */
-  if(data->easy_conn) {
-    data->easy_conn->data = NULL;
+  if(data->easy_conn)
     data->easy_conn = NULL;
-  }
 
 #ifdef USE_LIBPSL
   /* Remove the PSL association. */
index 5cd286650da1a9e90538d5fb0f0880f7279cef3c..2ec45873fb4e1306a063cb33b6137fd885b2b7ed 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -769,7 +769,6 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
     return CURLE_OK;
   }
 
-  conn->data = data;
   if(conn->dns_entry != NULL) {
     Curl_resolv_unlock(data, conn->dns_entry);
     conn->dns_entry = NULL;
@@ -788,14 +787,13 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
 
     /* unlink ourselves! */
   infof(data, "Closing connection %ld\n", conn->connection_id);
-  Curl_conncache_remove_conn(conn, TRUE);
+  Curl_conncache_remove_conn(data, conn, TRUE);
 
   free_idnconverted_hostname(&conn->host);
   free_idnconverted_hostname(&conn->conn_to_host);
   free_idnconverted_hostname(&conn->http_proxy.host);
   free_idnconverted_hostname(&conn->socks_proxy.host);
 
-  DEBUGASSERT(conn->data == data);
   /* this assumes that the pointer is still there after the connection was
      detected from the cache */
   Curl_ssl_close(conn, FIRSTSOCKET);
@@ -960,8 +958,6 @@ static bool extract_if_dead(struct connectdata *conn,
        handles in pipeline and the connection isn't already marked in
        use */
     bool dead;
-
-    conn->data = data;
     if(conn->handler->connection_check) {
       /* The protocol has a special method for checking the state of the
          connection. Use it to check if the connection is dead. */
@@ -977,8 +973,7 @@ static bool extract_if_dead(struct connectdata *conn,
 
     if(dead) {
       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
-      Curl_conncache_remove_conn(conn, FALSE);
-      conn->data = NULL; /* detach */
+      Curl_conncache_remove_conn(data, conn, FALSE);
       return TRUE;
     }
   }