there's a window in which the connect timeout can still run
after a recv completion, in which case we do want to clear the
query but we don't want to perform the extra handle detach.
On FreeBSD, we sometimes see spurious transient EADDRINUSE errors
when connecting to a UDP socket. We now try a few times to ensure
the error is real before giving up.
This commit also fixes a memory leak that occurred if an error was
encountered in isc__nm_async_udpconnect().
one of the tests in the resolver system test depends on dig
getting no response to its first two query attempts, and SERVFAIL
on the third after resolution times out.
using a 5-second retry timer in dig means the SERVFAIL response
could occur while dig is discarding the second query and preparing
to send the third. in this case the server's response could be
missed. shortening the retry interval to 4 seconds ensures that
dig has already sent the third query when the SERVFAIL response
arrives.
resending UDP queries using the same query object could result
in a recv completion event for a previous query arriving before
the send completion event for the current one, leading to
inconsistencies that could cause crashes or hangs on shutdown.
creating a new query context for each send fixes the problem.
when the code to handle TCP connect timeouts was moved out of
connect_timeout(), it caused hangs when dig connected via TCP to a
server and the connection succeded but the server never sent a
response. we should add a read timeout mechanism for client TCP
connections as well as a connect timeout mechanism. in the meantime,
however, I've restored the TCP functionality in connect_timeout()
so it can handle the case of read timeouts.
- stop and clean up resources from the TCP connect timer in
isc__nm_tcp_shutdown(), and call the connect callback with
ISC_R_CANCELED
- don't clear TCP queries that are waiting for connect in
clear_query(); they'll be taken care of by tcp_connected() now.
If we clone the csock (children socket) in TCP accept_connection() instead of
passing the ssock (server socket) to the call back and cloning it there we
unbreak the assumption that every socket is handled inside it's own worker
thread and therefore we can get rid of (at least) callback locking.
The uv_udp_connect() function is available from libuv 1.27+, move the code to
connect to udp socket to a (limited) shim function called isc_uv_udp_connect().
Attempting to connect dig to the wrong address via TCP caused a hang on
shutdown due to a dangling socket reference; tcp_connect_cb() was never
reached and so the TCP socket was never detached.
This commit adds a connection timeout mechanism to isc_nm_tcpconnect()
and isc_nm_tcpdnsconnect().
NOTE: Currently this only works correctly with "dig +tries=1". If the
connection is retried, we get a segfault on shutdown in uv_walk(); I
haven't yet worked out why.
when dig is interrupted with SIGINT while a UDP connection is still
pending, it hangs due to recv_done() never being called. adding
an extra handle detach in cancel_all() corrects this, but is probably
not the correct way to fix it.
because dig now uses the netmgr, printing of response messages
happens in a different thread than setup. the IDN output filtering
procedure, which set using dns_name_settotextfilter(), is stored as
thread-local data, and so if it's set during setup, it won't be
accessible when printing. we now set it immediately before printing,
in the same thread, and clear it immedately afterward.
The network manager does not support returning UDP datagrams to
clients from unexpected sources; it is therefore not possible for
dig to accept them. The "+[no]unexpected" option has therefore
been removed from the dig command and its documentation.
- isc_nm_tcpdnsconnect() sets up up an outgoing TCP DNS connection
- isc_nm_udpconnect() sets up a connected UDP socket
- isc_nm_read() now supports UDP; it reads a single datagram and then
stops until the next time it's called.
these functions will later be used to support outgoing queries in dig,
dispatch, etc.