]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Pin the dns_dispatch to threads when reusing
authorOndřej Surý <ondrej@isc.org>
Wed, 4 Jan 2023 18:21:14 +0000 (19:21 +0100)
committerOndřej Surý <ondrej@isc.org>
Thu, 5 Jan 2023 09:20:47 +0000 (10:20 +0100)
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)

lib/dns/dispatch.c

index 8ebdde4cf352d50c02fb7684e92ecc5b454a99b2..2026ddae21f96687f9310de5bdd5ffdcf00d5dab 100644 (file)
@@ -105,7 +105,8 @@ struct dns_dispentry {
 
 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 */
@@ -1134,6 +1135,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type,
                .link = ISC_LINK_INITIALIZER,
                .active = ISC_LIST_INITIALIZER,
                .pending = ISC_LIST_INITIALIZER,
+               .tid = isc_nm_tid(),
                .magic = DISPATCH_MAGIC,
        };
 
@@ -1219,6 +1221,11 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
 
                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);