diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-01-29 16:21:08 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-02-02 18:18:10 +0100 |
commit | 21816aec6ade814e458040d45878ec9b69d220fc (patch) | |
tree | 694f0a16e806722373a29824c7aea10a72b30cbb | |
parent | 2dbe6694d18d947e4a8e21a7267f15d090585e48 (diff) | |
download | systemd-21816aec6ade814e458040d45878ec9b69d220fc.tar.gz |
resolved: use reference counting for DnsQueryCandidate objectsv246.10
Follow-up for 4ea8b443de. The logic that manages DnsQueryCandidate is rather
complicated: a calls to dns_query_complete() that wants to destroy a
DnsQueryCandidate can be nested inside a deep chain of calls. Using reference
counts seems like the simplest approach.
DnsSearchDomain already uses reference counting.
This patch effectively brings dns_query_candidate_go() to the state before
4ea8b443de, but wraps the iteration over DnsQueryCandidate.transactions in
dns_query_candidate_ref+dns_query_candidate_unref.
(cherry picked from commit 0e0fd08fc832b8f42e567d722d388eba086da5ff)
(cherry picked from commit ab9f7e1a51005f12d3bac83b86716d9d33048eb7)
-rw-r--r-- | src/resolve/resolved-dns-query.c | 31 | ||||
-rw-r--r-- | src/resolve/resolved-dns-query.h | 9 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 2 |
3 files changed, 21 insertions, 21 deletions
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index dd353cb1d5..9272ece369 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -25,6 +25,7 @@ static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScop if (!c) return -ENOMEM; + c->n_ref = 1; c->query = q; c->scope = s; @@ -47,7 +48,7 @@ static void dns_query_candidate_stop(DnsQueryCandidate *c) { } } -DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { +static DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { if (!c) return NULL; @@ -65,6 +66,8 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { return mfree(c); } +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(DnsQueryCandidate, dns_query_candidate, dns_query_candidate_free); + static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { DnsSearchDomain *next; @@ -127,15 +130,16 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource } static int dns_query_candidate_go(DnsQueryCandidate *c) { + _cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *keep_c = NULL; DnsTransaction *t; Iterator i; int r; unsigned n = 0; - bool notify = false; assert(c); - c->query->block_ready++; + /* Let's keep a reference to the query while we're operating */ + keep_c = dns_query_candidate_ref(c); /* Start the transactions that are not started yet */ SET_FOREACH(t, c->transactions, i) { @@ -143,21 +147,14 @@ static int dns_query_candidate_go(DnsQueryCandidate *c) { continue; r = dns_transaction_go(t); - if (r < 0) { - c->query->block_ready--; + if (r < 0) return r; - } - if (r == 0) - /* A transaction is complete. */ - notify = true; n++; } - c->query->block_ready--; - /* If there was nothing to start, then let's proceed immediately */ - if (n == 0 || notify) + if (n == 0) dns_query_candidate_notify(c); return 0; @@ -307,11 +304,11 @@ static void dns_query_stop(DnsQuery *q) { dns_query_candidate_stop(c); } -static void dns_query_free_candidates(DnsQuery *q) { +static void dns_query_unref_candidates(DnsQuery *q) { assert(q); while (q->candidates) - dns_query_candidate_free(q->candidates); + dns_query_candidate_unref(q->candidates); } static void dns_query_reset_answer(DnsQuery *q) { @@ -340,7 +337,7 @@ DnsQuery *dns_query_free(DnsQuery *q) { LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q); } - dns_query_free_candidates(q); + dns_query_unref_candidates(q); dns_question_unref(q->question_idna); dns_question_unref(q->question_utf8); @@ -509,7 +506,7 @@ static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) { } static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) { - _cleanup_(dns_query_candidate_freep) DnsQueryCandidate *c = NULL; + _cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *c = NULL; int r; assert(q); @@ -933,7 +930,7 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) dns_question_unref(q->question_utf8); q->question_utf8 = TAKE_PTR(nq_utf8); - dns_query_free_candidates(q); + dns_query_unref_candidates(q); dns_query_reset_answer(q); q->state = DNS_TRANSACTION_NULL; diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h index fcb6fdc00f..8b4766cf15 100644 --- a/src/resolve/resolved-dns-query.h +++ b/src/resolve/resolved-dns-query.h @@ -14,12 +14,14 @@ typedef struct DnsQuery DnsQuery; #include "resolved-dns-transaction.h" struct DnsQueryCandidate { + unsigned n_ref; + int error_code; + DnsQuery *query; DnsScope *scope; DnsSearchDomain *search_domain; - int error_code; Set *transactions; LIST_FIELDS(DnsQueryCandidate, candidates_by_query); @@ -101,8 +103,9 @@ enum { DNS_QUERY_RESTARTED, }; -DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c); -DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_free); +DnsQueryCandidate* dns_query_candidate_ref(DnsQueryCandidate*); +DnsQueryCandidate* dns_query_candidate_unref(DnsQueryCandidate*); +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_unref); void dns_query_candidate_notify(DnsQueryCandidate *c); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index acbeaeba5d..a03bac6eae 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -105,7 +105,7 @@ DnsScope* dns_scope_free(DnsScope *s) { dns_scope_abort_transactions(s); while (s->query_candidates) - dns_query_candidate_free(s->query_candidates); + dns_query_candidate_unref(s->query_candidates); hashmap_free(s->transactions_by_key); |