Tweak get_new_frec() behaviour in "force" mode.

get_new_frec() is not supposed to ever free an frec when
the force arg is set. Make this so. In theory, this fixes
a bug, but it's practically impossible to provoke and I have
no evidence that it has ever happened IRL.
This commit is contained in:
Simon Kelley
2025-08-21 13:21:27 +01:00
parent 18195e7bb2
commit b52d1d2017

View File

@@ -3128,36 +3128,40 @@ static struct frec *get_new_frec(time_t now, struct server *master, int force)
/* Don't free DNSSEC sub-queries here, as we may end up with /* Don't free DNSSEC sub-queries here, as we may end up with
dangling references to them. They'll go when their "real" query dangling references to them. They'll go when their "real" query
is freed. */ is freed. */
if (!f->dependent && !force) if (!f->dependent)
#endif #endif
{ if (!force)
if (difftime(now, f->time) >= 4*TIMEOUT) {
{ if (difftime(now, f->time) >= 4*TIMEOUT)
daemon->metrics[METRIC_DNS_UNANSWERED_QUERY]++; {
free_frec(f); daemon->metrics[METRIC_DNS_UNANSWERED_QUERY]++;
target = f; free_frec(f);
} target = f;
else if (!oldest || difftime(f->time, oldest->time) <= 0) }
oldest = f; else if (!oldest || difftime(f->time, oldest->time) <= 0)
} oldest = f;
}
} }
if (f->sentto && ((int)difftime(now, f->time)) < TIMEOUT && server_samegroup(f->sentto, master)) if (f->sentto && ((int)difftime(now, f->time)) < TIMEOUT && server_samegroup(f->sentto, master))
count++; count++;
} }
if (!force && count >= daemon->ftabsize) if (!force)
{ {
query_full(now, master->domain); if (count >= daemon->ftabsize)
return NULL; {
} query_full(now, master->domain);
return NULL;
}
if (!target && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT) if (!target && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
{ {
/* can't find empty one, use oldest if there is one and it's older than timeout */ /* can't find empty one, use oldest if there is one and it's older than timeout */
daemon->metrics[METRIC_DNS_UNANSWERED_QUERY]++; daemon->metrics[METRIC_DNS_UNANSWERED_QUERY]++;
free_frec(oldest); free_frec(oldest);
target = oldest; target = oldest;
}
} }
if (!target && (target = (struct frec *)whine_malloc(sizeof(struct frec)))) if (!target && (target = (struct frec *)whine_malloc(sizeof(struct frec))))