Don't requeue any queries for getaddrinfo() during destruction. (#553)

During ares_destroy(), any outstanding queries are terminated, however ares_getaddrinfo() had an ordering issue with status codes which in some circumstances could lead to a new query being enqueued rather than honoring the termination.

Fixes #532
Fix By: @Chilledheart and Brad House (@bradh352)
pull/557/head
Brad House 1 year ago committed by GitHub
parent 21f3b77440
commit 1c3a52b510
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 78
      src/lib/ares_getaddrinfo.c

@ -598,56 +598,40 @@ static void host_callback(void *arg, int status, int timeouts,
hquery->timeouts += timeouts; hquery->timeouts += timeouts;
hquery->remaining--; hquery->remaining--;
if (status == ARES_SUCCESS) if (status == ARES_SUCCESS) {
{ addinfostatus = ares__parse_into_addrinfo(abuf, alen, 1, hquery->port,
addinfostatus = ares__parse_into_addrinfo(abuf, alen, 1, hquery->port, hquery->ai); hquery->ai);
if (addinfostatus == ARES_SUCCESS && alen >= HFIXEDSZ) if (addinfostatus == ARES_SUCCESS && alen >= HFIXEDSZ) {
{ qid = DNS_HEADER_QID(abuf); /* Converts to host byte order */
qid = DNS_HEADER_QID(abuf); /* Converts to host byte order */ terminate_retries(hquery, qid);
terminate_retries(hquery, qid);
}
} }
}
if (!hquery->remaining) if (!hquery->remaining) {
{ if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA) {
if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA) /* error in parsing result e.g. no memory */
{ if (addinfostatus == ARES_EBADRESP && hquery->ai->nodes) {
/* error in parsing result e.g. no memory */ /* We got a bad response from server, but at least one query
if (addinfostatus == ARES_EBADRESP && hquery->ai->nodes) * ended with ARES_SUCCESS */
{ end_hquery(hquery, ARES_SUCCESS);
/* We got a bad response from server, but at least one query } else {
* ended with ARES_SUCCESS */ end_hquery(hquery, addinfostatus);
end_hquery(hquery, ARES_SUCCESS); }
} } else if (hquery->ai->nodes) {
else /* at least one query ended with ARES_SUCCESS */
{ end_hquery(hquery, ARES_SUCCESS);
end_hquery(hquery, addinfostatus); } else if (status == ARES_EDESTRUCTION || status == ARES_ECANCELLED) {
} /* must make sure we don't do next_lookup() on destroy or cancel */
} end_hquery(hquery, status);
else if (hquery->ai->nodes) } else if (status == ARES_ENOTFOUND || status == ARES_ENODATA ||
{ addinfostatus == ARES_ENODATA) {
/* at least one query ended with ARES_SUCCESS */ if (status == ARES_ENODATA || addinfostatus == ARES_ENODATA)
end_hquery(hquery, ARES_SUCCESS); hquery->nodata_cnt++;
} next_lookup(hquery, hquery->nodata_cnt?ARES_ENODATA:status);
else if (status == ARES_ENOTFOUND || status == ARES_ENODATA || } else {
addinfostatus == ARES_ENODATA) end_hquery(hquery, status);
{
if (status == ARES_ENODATA || addinfostatus == ARES_ENODATA)
hquery->nodata_cnt++;
next_lookup(hquery, hquery->nodata_cnt?ARES_ENODATA:status);
}
else if (status == ARES_EDESTRUCTION)
{
/* NOTE: Could also be ARES_EDESTRUCTION. We need to only call this
* once all queries (there can be multiple for getaddrinfo) are
* terminated. */
end_hquery(hquery, status);
}
else
{
end_hquery(hquery, status);
}
} }
}
/* at this point we keep on waiting for the next query to finish */ /* at this point we keep on waiting for the next query to finish */
} }

Loading…
Cancel
Save