]> granicus.if.org Git - curl/commitdiff
move Curl_share_lock and ref counting into Curl_fetch_addr
authorStefan Bühler <buehler@teamviewer.com>
Tue, 17 Mar 2015 08:26:36 +0000 (09:26 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 3 Apr 2015 14:46:14 +0000 (16:46 +0200)
lib/hostip.c
lib/hostip.h
lib/multi.c

index 05f3ed0b59e2873ea8307dfc26f18d7ddae62187..fb62b8ccae3541821feeaa4915f0edd323afa131 100644 (file)
@@ -311,19 +311,9 @@ remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns)
 sigjmp_buf curl_jmpenv;
 #endif
 
-/*
- * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
- *
- * Curl_resolv() checks initially and multi_runsingle() checks each time
- * it discovers the handle in the state WAITRESOLVE whether the hostname
- * has already been resolved and the address has already been stored in
- * the DNS cache. This short circuits waiting for a lot of pending
- * lookups for the same hostname requested by different handles.
- *
- * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
- */
-struct Curl_dns_entry *
-Curl_fetch_addr(struct connectdata *conn,
+/* lookup address, returns entry if found and not stale */
+static struct Curl_dns_entry *
+fetch_addr(struct connectdata *conn,
                 const char *hostname,
                 int port)
 {
@@ -344,15 +334,57 @@ Curl_fetch_addr(struct connectdata *conn,
   /* See if its already in our dns cache */
   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
 
+  if(dns && (data->set.dns_cache_timeout != -1))  {
+    /* See whether the returned entry is stale. Done before we release lock */
+    struct hostcache_prune_data user;
+
+    time(&user.now);
+    user.cache_timeout = data->set.dns_cache_timeout;
+
+    if(hostcache_timestamp_remove(&user, dns)) {
+      infof(data, "Hostname in DNS cache was stale, zapped\n");
+      dns = NULL; /* the memory deallocation is being handled by the hash */
+      Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1);
+    }
+  }
+
   /* free the allocated entry_id again */
   free(entry_id);
 
-  /* See whether the returned entry is stale. Done before we release lock */
-  stale = remove_entry_if_stale(data, dns);
-  if(stale) {
-    infof(data, "Hostname in DNS cache was stale, zapped\n");
-    dns = NULL; /* the memory deallocation is being handled by the hash */
-  }
+  return dns;
+}
+
+/*
+ * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ *
+ * Curl_resolv() checks initially and multi_runsingle() checks each time
+ * it discovers the handle in the state WAITRESOLVE whether the hostname
+ * has already been resolved and the address has already been stored in
+ * the DNS cache. This short circuits waiting for a lot of pending
+ * lookups for the same hostname requested by different handles.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ *
+ * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
+ * use, or we'll leak memory!
+ */
+struct Curl_dns_entry *
+Curl_fetch_addr(struct connectdata *conn,
+                const char *hostname,
+                int port)
+{
+  struct SessionHandle *data = conn->data;
+  struct Curl_dns_entry *dns = NULL;
+
+  if(data->share)
+    Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+  dns = fetch_addr(conn, hostname, port);
+
+  if(dns) dns->inuse++; /* we use it! */
+
+  if(data->share)
+    Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
 
   return dns;
 }
@@ -451,7 +483,7 @@ int Curl_resolv(struct connectdata *conn,
   if(data->share)
     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
 
-  dns = Curl_fetch_addr(conn, hostname, port);
+  dns = fetch_addr(conn, hostname, port);
 
   if(dns) {
     infof(data, "Hostname %s was found in DNS cache\n", hostname);
index 0e2e2cf7ff441e8dce5226c6ec0624b3f822fb5c..a79b89a44bbfd94b1e2001c0401670b632747c38 100644 (file)
@@ -174,6 +174,9 @@ const char *Curl_printable_address(const Curl_addrinfo *ip,
  * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
  *
  * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ *
+ * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
+ * use, or we'll leak memory!
  */
 struct Curl_dns_entry *
 Curl_fetch_addr(struct connectdata *conn,
index c30835c3f5a77a43147ea669ebf92d65721b7099..235b5b457fdfd23200547e84c8ddf9ea7e2390ae 100644 (file)
@@ -1112,13 +1112,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       struct connectdata *conn = data->easy_conn;
 
       /* check if we have the name resolved by now */
-      if(data->share)
-        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
       dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port);
 
       if(dns) {
-        dns->inuse++; /* we use it! */
 #ifdef CURLRES_ASYNCH
         conn->async.dns = dns;
         conn->async.done = TRUE;
@@ -1127,9 +1123,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         infof(data, "Hostname was found in DNS cache\n");
       }
 
-      if(data->share)
-        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
-
       if(!dns)
         result = Curl_resolver_is_resolved(data->easy_conn, &dns);