mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
- Constantine Sapuntzakis posted bug #2891595
(http://curl.haxx.se/bug/view.cgi?id=2891595) which identified how an entry in the DNS cache would linger too long if the request that added it was in use that long. He also provided the patch that now makes libcurl capable of still doing a request while the DNS hash entry may get timed out.
This commit is contained in:
parent
107c4d878a
commit
fb5f332834
6
CHANGES
6
CHANGES
@ -7,6 +7,12 @@
|
|||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
Daniel Stenberg (11 Nov 2009)
|
Daniel Stenberg (11 Nov 2009)
|
||||||
|
- Constantine Sapuntzakis posted bug #2891595
|
||||||
|
(http://curl.haxx.se/bug/view.cgi?id=2891595) which identified how an entry
|
||||||
|
in the DNS cache would linger too long if the request that added it was in
|
||||||
|
use that long. He also provided the patch that now makes libcurl capable of
|
||||||
|
still doing a request while the DNS hash entry may get timed out.
|
||||||
|
|
||||||
- Christian Schmitz noticed that the progress meter/callback was not properly
|
- Christian Schmitz noticed that the progress meter/callback was not properly
|
||||||
used during the FTP connection phase (after the actual TCP connect), while
|
used during the FTP connection phase (after the actual TCP connect), while
|
||||||
it of course should be. I also made the speed check get called correctly so
|
it of course should be. I also made the speed check get called correctly so
|
||||||
|
@ -16,6 +16,7 @@ This release includes the following bugfixes:
|
|||||||
o progress meter percentage and transfer time estimates fixes
|
o progress meter percentage and transfer time estimates fixes
|
||||||
o portability enhancement for OS's without orthogonal directory tree structure
|
o portability enhancement for OS's without orthogonal directory tree structure
|
||||||
o progress meter/callback during FTP connection
|
o progress meter/callback during FTP connection
|
||||||
|
o DNS cache timeout while transfer in progress
|
||||||
|
|
||||||
This release includes the following known bugs:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
@ -24,6 +25,6 @@ This release includes the following known bugs:
|
|||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Yang Tse, Kamil Dudka, Christian Schmitz
|
Yang Tse, Kamil Dudka, Christian Schmitz, Constantine Sapuntzakis
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
@ -140,8 +140,8 @@ mk_hash_element(const void *key, size_t key_len, const void *p)
|
|||||||
|
|
||||||
#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
|
#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
|
||||||
|
|
||||||
/* Return the data in the hash. If there already was a match in the hash,
|
/* Insert the data in the hash. If there already was a match in the hash,
|
||||||
that data is returned. */
|
that data is replaced. */
|
||||||
void *
|
void *
|
||||||
Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
|
Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
|
||||||
{
|
{
|
||||||
@ -152,8 +152,9 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
|
|||||||
for (le = l->head; le; le = le->next) {
|
for (le = l->head; le; le = le->next) {
|
||||||
he = (struct curl_hash_element *) le->ptr;
|
he = (struct curl_hash_element *) le->ptr;
|
||||||
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
||||||
h->dtor(p); /* remove the NEW entry */
|
Curl_llist_remove(l, le, (void *)h);
|
||||||
return he->ptr; /* return the EXISTING entry */
|
--h->size;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
lib/hostip.c
46
lib/hostip.c
@ -123,6 +123,10 @@
|
|||||||
static struct curl_hash hostname_cache;
|
static struct curl_hash hostname_cache;
|
||||||
static int host_cache_initialized;
|
static int host_cache_initialized;
|
||||||
|
|
||||||
|
#ifdef CURLDEBUG
|
||||||
|
static int ndns = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void freednsentry(void *freethis);
|
static void freednsentry(void *freethis);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -232,14 +236,7 @@ hostcache_timestamp_remove(void *datap, void *hc)
|
|||||||
(struct hostcache_prune_data *) datap;
|
(struct hostcache_prune_data *) datap;
|
||||||
struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
|
struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
|
||||||
|
|
||||||
if((data->now - c->timestamp < data->cache_timeout) ||
|
return (data->now - c->timestamp >= data->cache_timeout);
|
||||||
c->inuse) {
|
|
||||||
/* please don't remove */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fine, remove */
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -339,7 +336,6 @@ Curl_cache_addr(struct SessionHandle *data,
|
|||||||
size_t entry_len;
|
size_t entry_len;
|
||||||
struct Curl_dns_entry *dns;
|
struct Curl_dns_entry *dns;
|
||||||
struct Curl_dns_entry *dns2;
|
struct Curl_dns_entry *dns2;
|
||||||
time_t now;
|
|
||||||
|
|
||||||
/* Create an entry id, based upon the hostname and port */
|
/* Create an entry id, based upon the hostname and port */
|
||||||
entry_id = create_hostcache_id(hostname, port);
|
entry_id = create_hostcache_id(hostname, port);
|
||||||
@ -357,23 +353,22 @@ Curl_cache_addr(struct SessionHandle *data,
|
|||||||
|
|
||||||
dns->inuse = 0; /* init to not used */
|
dns->inuse = 0; /* init to not used */
|
||||||
dns->addr = addr; /* this is the address(es) */
|
dns->addr = addr; /* this is the address(es) */
|
||||||
|
time(&dns->timestamp);
|
||||||
|
if(dns->timestamp == 0)
|
||||||
|
dns->timestamp = 1; /* zero indicates that entry isn't in hash table */
|
||||||
|
|
||||||
/* Store the resolved data in our DNS cache. This function may return a
|
/* Store the resolved data in our DNS cache. */
|
||||||
pointer to an existing struct already present in the hash, and it may
|
|
||||||
return the same argument we pass in. Make no assumptions. */
|
|
||||||
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
|
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
|
||||||
(void *)dns);
|
(void *)dns);
|
||||||
if(!dns2) {
|
if(!dns2) {
|
||||||
/* Major badness, run away. */
|
|
||||||
free(dns);
|
free(dns);
|
||||||
free(entry_id);
|
free(entry_id);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
time(&now);
|
|
||||||
dns = dns2;
|
|
||||||
|
|
||||||
dns->timestamp = now; /* used now */
|
dns = dns2;
|
||||||
dns->inuse++; /* mark entry as in-use */
|
dns->inuse++; /* mark entry as in-use */
|
||||||
|
DEBUGF(ndns++);
|
||||||
|
|
||||||
/* free the allocated entry_id again */
|
/* free the allocated entry_id again */
|
||||||
free(entry_id);
|
free(entry_id);
|
||||||
@ -436,6 +431,7 @@ int Curl_resolv(struct connectdata *conn,
|
|||||||
|
|
||||||
if(dns) {
|
if(dns) {
|
||||||
dns->inuse++; /* we use it! */
|
dns->inuse++; /* we use it! */
|
||||||
|
DEBUGF(ndns++);
|
||||||
rc = CURLRESOLV_RESOLVED;
|
rc = CURLRESOLV_RESOLVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,6 +684,13 @@ void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
|
|||||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||||
|
|
||||||
dns->inuse--;
|
dns->inuse--;
|
||||||
|
DEBUGF(ndns--);
|
||||||
|
/* only free if nobody is using AND it is not in hostcache (timestamp ==
|
||||||
|
0) */
|
||||||
|
if (dns->inuse == 0 && dns->timestamp == 0) {
|
||||||
|
Curl_freeaddrinfo(dns->addr);
|
||||||
|
free(dns);
|
||||||
|
}
|
||||||
|
|
||||||
if(data->share)
|
if(data->share)
|
||||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||||
@ -700,12 +703,21 @@ static void freednsentry(void *freethis)
|
|||||||
{
|
{
|
||||||
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
|
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
|
||||||
|
|
||||||
if(p) {
|
/* mark the entry as not in hostcache */
|
||||||
|
p->timestamp = 0;
|
||||||
|
if (p->inuse == 0) {
|
||||||
Curl_freeaddrinfo(p->addr);
|
Curl_freeaddrinfo(p->addr);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CURLDEBUG
|
||||||
|
int curl_get_ndns(void)
|
||||||
|
{
|
||||||
|
return ndns;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
|
* Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
|
||||||
*/
|
*/
|
||||||
|
@ -121,6 +121,8 @@ void Curl_global_host_cache_dtor(void);
|
|||||||
|
|
||||||
struct Curl_dns_entry {
|
struct Curl_dns_entry {
|
||||||
Curl_addrinfo *addr;
|
Curl_addrinfo *addr;
|
||||||
|
/* timestamp == 0 -- entry not in hostcache
|
||||||
|
timestamp != 0 -- entry is in hostcache */
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
long inuse; /* use-counter, make very sure you decrease this
|
long inuse; /* use-counter, make very sure you decrease this
|
||||||
when you're done using the address you received */
|
when you're done using the address you received */
|
||||||
|
Loading…
Reference in New Issue
Block a user