]> 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 08:11:42 +0000 (09:11 +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.

lib/dns/dispatch.c

index c1dbff4c782f04062d37e95a73a5be403bc020f0..9d2b7732af0c1fbaa286058069fd66017da1f385 100644 (file)
@@ -29,6 +29,7 @@
 #include <isc/random.h>
 #include <isc/stats.h>
 #include <isc/string.h>
+#include <isc/tid.h>
 #include <isc/time.h>
 #include <isc/tls.h>
 #include <isc/util.h>
@@ -109,7 +110,8 @@ struct dns_dispentry {
 
 struct dns_dispatch {
        /* Unlocked. */
-       unsigned int magic;     /*%< magic */
+       unsigned int magic; /*%< magic */
+       uint32_t tid;
        dns_dispatchmgr_t *mgr; /*%< dispatch manager */
        isc_nmhandle_t *handle; /*%< netmgr handle for TCP connection */
        isc_sockaddr_t local;   /*%< local address */
@@ -1160,6 +1162,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_tid(),
                .magic = DISPATCH_MAGIC,
        };
 
@@ -1245,6 +1248,11 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
 
                LOCK(&disp->lock);
 
+               if (disp->tid != isc_tid()) {
+                       UNLOCK(&disp->lock);
+                       continue;
+               }
+
                if (disp->handle != NULL) {
                        sockname = isc_nmhandle_localaddr(disp->handle);
                        peeraddr = isc_nmhandle_peeraddr(disp->handle);