Previously, dns_dispatch_gettcp() could pick a TCP connection created by
different thread - this breaks our contractual promise to DNS dispatch
by using the TCP connection on a different thread than it was created.
Add .tid member to the dns_dispatch_t struct and skip the dispatches
from other threads when looking up a TCP dispatch that we can reuse in
dns_request.
NOTE: This is going to be properly refactored, but this change could be
also backported to 9.18 for better stability and thread-affinity.
(cherry picked from commit
1a999353cd496b6cc0d6a6ede3948a0b4cce3e4b)
struct dns_dispatch {
/* Unlocked. */
- unsigned int magic; /*%< magic */
+ unsigned int magic; /*%< magic */
+ int tid;
dns_dispatchmgr_t *mgr; /*%< dispatch manager */
isc_nmhandle_t *handle; /*%< netmgr handle for TCP connection */
isc_sockaddr_t local; /*%< local address */
.link = ISC_LINK_INITIALIZER,
.active = ISC_LIST_INITIALIZER,
.pending = ISC_LIST_INITIALIZER,
+ .tid = isc_nm_tid(),
.magic = DISPATCH_MAGIC,
};
LOCK(&disp->lock);
+ if (disp->tid != isc_nm_tid()) {
+ UNLOCK(&disp->lock);
+ continue;
+ }
+
if (disp->handle != NULL) {
sockname = isc_nmhandle_localaddr(disp->handle);
peeraddr = isc_nmhandle_peeraddr(disp->handle);