We have further investigated the crash related to name resolution and for us it
is because there is a threading problem with the use of a shared DNS cache
(data->hostcache) in the multi interface. Indeed, even if the multi interface is
only accessed by one thread, its DNS cache could be accessed at the same time by
several. There are two cases where it can happen (imagine we have two easy
handles in a multi interface) :
1. the thread of the multi interface is processing Curl_disconnect() on its
first easy handle because the handle has finished its transfer and connection
could not be reused (because of the server or with Curl option) and at the same
time the callback from the host resolver thread for the second easy handle is
called and tries to insert a new hash entry in the DNS cache (indeed the two
easy handle DNS cache pointers are pointing to the DNS cache of their multi
interface) 2. the thread of the multi interface is processing
curl_multi_remove_handle() on an easy handle because the application has decided
to remove this handle (for example we decided to abort the transfer) even before
the name resolution succeeds. In this case, the data->hostcache pointer is set
to 0 in the easy handle structure and thus the callback would call
Curl_hash_add() with h=0, which would crash in FETCH_LIST().
We have reproduced case 2. quite easily in a test case but unfortunately case 1.
is much more difficult to reproduce (it happened once in 6 months).
Thus a solution for problem 1. could be to protect the access to the shared DNS
cache and for problem 2. the value of h could be tested either in
Curl_cache_addr() or Curl_hash_add().
Do you agree with this analysis or is there a flaw in our way of thinking ?
Which solution do you recommend ? Can we use the multi and the share at the same
time (ie adding an easy handle with option CURLOPT_SHARE in a multi interface) ?
Thanks in advance,
Cyril Picat & Sebastien Trottier
Received on 2007-03-18