4.6 Servers, Attempts and Timeouts
Server order, demotion and the attempt limit are set by PSPU §6.7, and the contract's mainline values are in PSPU §6.B. resolvd's values are:
| Bound | Value |
|---|---|
| Transaction timeout | 2 s |
| Attempts per question (all candidates and transports) | 3 |
| Demotion period | 30 s |
| Upstream transactions in flight | 4 096 |
4.6.1 Choosing the server #
- For each attempt, the scope's servers — or the fallback servers — are put in order: the servers not currently demoted, in their configured order, followed by the demoted ones, in their configured order.
- The attempt goes to the first server in that order not yet asked for this candidate. When every server has been asked, it goes to the server at position n mod count in that order, where n is the number of attempts already made for the candidate.
- With one server, all three attempts go to it.
- The order is computed afresh for each attempt, so a server demoted by the previous attempt is already behind its peers for the next.
- Attempts for one candidate are made one at a time; a transaction is sent only after the previous one for the same candidate has ended.
With two healthy servers A and B, the attempts go to A, B, then
whichever of them is first in the order at that moment — A if both
have since been demoted, since demotion keeps configured order within
the demoted group.
4.6.2 What fails an attempt #
Each of the following ends the transaction, adds one to
upstream_failed, demotes the server, and moves to the next attempt:
- no matching reply within 2 seconds of the transaction being sent;
- an error opening, binding, connecting or sending on the transaction's socket, except the local resource and permission errors below — an unreachable network is known at once, not after the timeout;
- an error receiving on a UDP socket, such as the refusal that follows an ICMP port-unreachable;
- for TCP, the connection failing to complete: an error or hang-up while it is being established;
- for TCP, an error, a hang-up or a failed write before the whole query has been sent;
- for TCP, the connection closing, or a read error, before a whole matching reply has arrived;
- a matching reply whose response code is neither
NOERRORnorNXDOMAIN—SERVFAIL,REFUSED,FORMERR,NOTIMP, and every other code, including EDNS extended codes.
A synchronous failure to open or send a transaction caused by exhausted
local descriptors (EMFILE, ENFILE), memory or buffers (ENOMEM,
ENOBUFS), local address allocation (EADDRNOTAVAIL, EADDRINUSE), or
permission (EACCES, EPERM) still adds one upstream_failed and advances
the bounded retry sequence, but does not demote the server. A different
configured address or address family may still be usable. If all attempts
fail, the result is unavailable and is not cached.
A reply that does not match the transaction is ignored while the socket remains open for a matching reply until the original deadline (§4.8).
4.6.3 Demotion #
- Demoting a server marks its address until 30 seconds from now; a further failure moves that mark forward.
- A matching reply with response code
NOERRORorNXDOMAINthat resolvd uses — a UDP reply withoutTC, or a TCP reply — removes the server's mark at once. A UDP reply withTCset does not remove it, whatever its response code; the reply to the TCP retry decides. - The mark belongs to the address, so a server listed by two scopes is demoted in both.
- A demoted server is still asked, after the healthy ones.
statuslists, for each scope, which of its servers are demoted at that moment (§5.3); demotion of the fallback servers is not reported.
4.6.4 The attempt limit #
- A question gets three upstream attempts across all search candidates and
transports. Failures spend them: a timeout, a failure response code, or
a transport failure. When its last attempt fails, the question is
unavailable(§4.1). - The budget is not reset when the question moves to another candidate,
but a candidate's
NXDOMAINthat moves it on is an answer, not a failure, and does not spend an attempt. Every search candidate is therefore asked, however many there are. Cached answers spend no attempt. - The TCP retry following a truncated UDP reply (§4.7) spends one attempt
and gets its own two-second deadline. A truncated reply on the final
attempt cannot start TCP: the question is
unavailable.
The three attempts allow at most six seconds of upstream timeout waiting
in total, including TCP and search-domain expansion. Each NXDOMAIN that
moves to another candidate adds one round trip. Loop scheduling and local
I/O can add elapsed time; the attempt limit does not give those
operations a separate deadline.
4.6.5 The in-flight ceiling #
- When 4 096 or more transactions are outstanding, a question about to
allocate an upstream transaction is answered
unavailableat once, and therefusedcounter goes up by one. A question whose scope has no servers left is answeredunavailablebefore the ceiling is looked at, and is not counted as refused. - Every send checks this ceiling, including later attempts and TCP retries. A retry is normally sent after its previous transaction has ended and been removed, so it can reuse that slot even at capacity. Exhausting the three-attempt budget is checked before allocating a transaction, and is not counted as a capacity refusal.
- Synthetic names and cache hits are answered as usual whatever the count.