Tested on: Ubuntu/Linux 3.11.0-12-generic, curl 7.34.0-DEV.
This has already been discussed at the curl-library mailing list.
I use the multi interface to cache the connections to some server between requests and CURLOPT_RESOLVE to populate the DNS cache (my scenario is a private GPRS network with no working DNS servers). But even though I initialize the DNS entries with every easy handle libcurl sometimes considers them expired when initiating the connection. As a result libcurl tries to reach one of the default DNS servers, which always results in a CURLE_COULDNT_RESOLVE_HOST in my case.
The documentation states that CURLOPT_RESOLVE just pre-populates the DNS cache, which implies it should follow the same rules about expiration. But since I'm setting the option with every easy handle I would expect the entries to be "refreshed". Moreover, there's a timing issue: depending on how much you wait before the requests libcurl will indeed "refresh" the entries. So, at the very least, the behaviour is not consistent.
I attached a program demonstrating the problem, also available at: https://gist.github.com/romuloceccon/6941606. It outputs the following. Note that you can't reproduce it when omitting the call to sleep():
debug: Added fake.host:80:137.56.161.173 to DNS cache
debug: About to connect() to fake.host port 80 (#0)
debug: Trying 137.56.161.173...
debug: Adding handle: conn: 0xb81160
debug: Adding handle: send: 0
debug: Adding handle: recv: 0
debug: Curl_addHandleToPipeline: length: 1
debug: - Conn 0 (0xb81160) send_pipe: 1, recv_pipe: 0
debug: Connected to fake.host (137.56.161.173) port 80 (#0)
debug: Server lighttpd/1.4.28 is not blacklisted
debug: Closing connection 0
HTTP transfer completed with status 0
debug: Added fake.host:80:137.56.161.173 to DNS cache
debug: getaddrinfo(3) failed for fake.host:80
debug: Couldn't resolve host 'fake.host'
debug: Closing connection 1
HTTP transfer completed with status 6
I managed to fix it by patching Curl_loadhostpairs() with code copied from Curl_cache_addr(), but because of the timing issue I think it's just covering the real bug somewhere else:
diff --git a/lib/hostip.c b/lib/hostip.c
index f37b492..4157a2a 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -807,8 +807,15 @@ CURLcode Curl_loadhostpairs(struct SessionHandle *data)
/* if not in the cache already, put this host in the cache */
dns = Curl_cache_addr(data, addr, hostname, port);
else
+ {
/* this is a duplicate, free it again */
Curl_freeaddrinfo(addr);
+
+ /* reset timestamp */
+ time(&dns->timestamp);
+ if(dns->timestamp == 0)
+ dns->timestamp = 1; /* zero indicates that entry isn't in hash table */
+ }
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
The documentation changed since I started the discussion on the mailing list. So, please, ignore the paragraph where I talk about it (I don't have permission to edit the ticket).
Thanks for your report. This bug has now been fixed in git, commit 030a2b8cb8c4f1d.