diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index c4d620ac8b..757fbedf99 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -133,23 +133,33 @@ static int dns_query_candidate_go(DnsQueryCandidate *c) { DnsTransaction *t; int r; unsigned n = 0; + bool notify = false; assert(c); + c->query->block_ready++; + /* Start the transactions that are not started yet */ SET_FOREACH(t, c->transactions) { if (t->state != DNS_TRANSACTION_NULL) continue; r = dns_transaction_go(t); - if (r < 0) + if (r < 0) { + c->query->block_ready--; 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) + if (n == 0 || notify) dns_query_candidate_notify(c); return 0; diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index b20a61a401..7c966affe1 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -152,8 +152,8 @@ bool dns_transaction_gc(DnsTransaction *t) { static uint16_t pick_new_id(Manager *m) { uint16_t new_id; - /* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the number of - * transactions, and it's much lower than the space of IDs. */ + /* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the + * number of transactions, and it's much lower than the space of IDs. */ assert_cc(TRANSACTIONS_MAX < 0xFFFF); @@ -1333,6 +1333,10 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) { assert(t); + /* Returns 0 if dns_transaction_complete() has been called. In that case the transaction and query + * candidate objects may have been invalidated and must not be accessed. Returns 1 if the transaction + * has been prepared. */ + dns_transaction_stop_timeout(t); if (!dns_scope_network_good(t->scope)) { @@ -1460,7 +1464,6 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) { } static int dns_transaction_make_packet_mdns(DnsTransaction *t) { - _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; bool add_known_answers = false; DnsTransaction *other; @@ -1628,8 +1631,9 @@ int dns_transaction_go(DnsTransaction *t) { assert(t); - /* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has finished - * now. */ + /* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has + * finished now. In the latter case, the transaction and query candidate objects must not be accessed. + */ assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); @@ -1687,7 +1691,7 @@ int dns_transaction_go(DnsTransaction *t) { t->state = DNS_TRANSACTION_PENDING; log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter); - return 0; + return 1; } /* Otherwise, we need to ask the network */