[master] hold a reference on fetch context during query

4094.	[bug]		A race during shutdown or reconfiguration could
			cause an assertion in mem.c. [RT #38979]
This commit is contained in:
Evan Hunt 2015-04-08 14:33:45 -07:00
parent 0d00a726fe
commit d9b37259f3
3 changed files with 39 additions and 10 deletions

View file

@ -1,3 +1,6 @@
4094. [bug] A race during shutdown or reconfiguration could
cause an assertion in mem.c. [RT #38979]
4093. [func] Dig now learns the SIT value from truncated
responses when it retries over TCP. [RT #39047]

View file

@ -581,6 +581,12 @@
in zt.c. [RT #37573]
</para>
</listitem>
<listitem>
<para>
A race during shutdown or reconfiguration could
cause an assertion failure in mem.c. [RT #38979]
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="end_of_life">

View file

@ -533,6 +533,8 @@ static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name,
dns_rdatatype_t type,
dns_name_t **noqname);
static void fctx_increference(fetchctx_t *fctx);
static isc_boolean_t fctx_decreference(fetchctx_t *fctx);
/*%
* Increment resolver-related statistics counters.
@ -815,10 +817,12 @@ fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
*/
#define fctx_stopidletimer fctx_starttimer
static inline void
resquery_destroy(resquery_t **queryp) {
dns_resolver_t *res;
isc_boolean_t empty;
resquery_t *query;
fetchctx_t *fctx;
REQUIRE(queryp != NULL);
query = *queryp;
@ -826,15 +830,21 @@ resquery_destroy(resquery_t **queryp) {
INSIST(query->tcpsocket == NULL);
query->fctx->nqueries--;
if (SHUTTINGDOWN(query->fctx)) {
dns_resolver_t *res = query->fctx->res;
if (maybe_destroy(query->fctx, ISC_FALSE))
empty_bucket(res);
}
fctx = query->fctx;
res = fctx->res;
fctx->nqueries--;
LOCK(&res->buckets[fctx->bucketnum].lock);
empty = fctx_decreference(query->fctx);
UNLOCK(&res->buckets[fctx->bucketnum].lock);
query->magic = 0;
isc_mem_put(query->mctx, query, sizeof(*query));
*queryp = NULL;
if (empty)
empty_bucket(res);
}
static void
@ -1621,6 +1631,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
}
query->dispentry = NULL;
fctx_increference(fctx);
query->fctx = fctx;
query->tsig = NULL;
query->tsigkey = NULL;
@ -6970,10 +6981,21 @@ answer_response(fetchctx_t *fctx) {
return (result);
}
static void
fctx_increference(fetchctx_t *fctx) {
REQUIRE(VALID_FCTX(fctx));
LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
fctx->references++;
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
}
static isc_boolean_t
fctx_decreference(fetchctx_t *fctx) {
isc_boolean_t bucket_empty = ISC_FALSE;
REQUIRE(VALID_FCTX(fctx));
INSIST(fctx->references > 0);
fctx->references--;
if (fctx->references == 0) {
@ -8209,9 +8231,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);
else {
LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
fctx->references++;
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
fctx_increference(fctx);
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);