}
}
+static void dns_query_candidate_abandon(DnsQueryCandidate *c) {
+ DnsTransaction *t;
+
+ assert(c);
+
+ /* Abandon all the DnsTransactions attached to this query */
+
+ while ((t = set_steal_first(c->transactions))) {
+ t->wait_for_answer = true;
+ set_remove(t->notify_query_candidates, c);
+ set_remove(t->notify_query_candidates_done, c);
+ dns_transaction_gc(t);
+ }
+}
+
static DnsQueryCandidate* dns_query_candidate_unlink(DnsQueryCandidate *c) {
assert(c);
dns_query_candidate_stop(c);
}
+static void dns_query_abandon(DnsQuery *q) {
+ assert(q);
+
+ /* Thankfully transactions have their own timeouts */
+ event_source_disable(q->timeout_event_source);
+
+ LIST_FOREACH(candidates_by_query, c, q->candidates)
+ dns_query_candidate_abandon(c);
+}
+
static void dns_query_unlink_candidates(DnsQuery *q) {
assert(q);
(void) manager_monitor_send(q->manager, q);
- dns_query_stop(q);
+ dns_query_abandon(q);
if (q->complete)
q->complete(q);
}
if (t->block_gc > 0)
return t;
+ if (t->wait_for_answer && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING))
+ return t;
+
if (set_isempty(t->notify_query_candidates) &&
set_isempty(t->notify_query_candidates_done) &&
set_isempty(t->notify_zone_items) &&
unsigned block_gc;
+ /* Set when we're willing to let this transaction live beyond it's usefulness for the original query,
+ * for caching purposes. This blocks gc while there is still a chance we might still receive an
+ * answer. */
+ bool wait_for_answer;
+
LIST_FIELDS(DnsTransaction, transactions_by_scope);
LIST_FIELDS(DnsTransaction, transactions_by_stream);
LIST_FIELDS(DnsTransaction, transactions_by_key);