]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Always call the TCP dispatch connected callbacks asynchronously
authorOndřej Surý <ondrej@isc.org>
Mon, 4 Mar 2024 11:58:56 +0000 (12:58 +0100)
committerOndřej Surý <ondrej@isc.org>
Mon, 4 Mar 2024 15:34:14 +0000 (16:34 +0100)
The TCP dispatch connected callbacks could be called synchronously which
in turn could destroy xfrin before we return from dns_xfrin_create().

Delay the calling the callback called from tcp_dispatch_connect() by
calling it always asynchronously.

lib/dns/dispatch.c

index 603add2ba3548a52e3b3fff6ad7be43f06b2127c..e5412abe9eb455ebac686329d73a94a45abd4d2c 100644 (file)
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <isc/async.h>
 #include <isc/hash.h>
 #include <isc/hashmap.h>
 #include <isc/loop.h>
@@ -1776,6 +1777,16 @@ tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) {
        disp->reading = true;
 }
 
+static void
+resp_connected(void *arg) {
+       dns_dispentry_t *resp = arg;
+       dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s",
+                     isc_result_totext(resp->result));
+
+       resp->connected(resp->result, NULL, resp->arg);
+       dns_dispentry_detach(&resp); /* DISPENTRY005 */
+}
+
 static void
 tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
        dns_dispatch_t *disp = (dns_dispatch_t *)arg;
@@ -1846,10 +1857,7 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
                next = ISC_LIST_NEXT(resp, rlink);
                ISC_LIST_UNLINK(resps, resp, rlink);
 
-               dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s",
-                             isc_result_totext(resp->result));
-               resp->connected(resp->result, NULL, resp->arg);
-               dns_dispentry_detach(&resp); /* DISPENTRY005 */
+               resp_connected(resp);
        }
 
        dns_dispatch_detach(&disp); /* DISPATCH003 */
@@ -1999,10 +2007,9 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
                        tcp_startrecv(disp, resp);
                }
 
-               /* We are already connected; call the connected cb */
-               dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s",
-                             isc_result_totext(ISC_R_SUCCESS));
-               resp->connected(ISC_R_SUCCESS, NULL, resp->arg);
+               /* Already connected; call the connected cb asynchronously */
+               dns_dispentry_ref(resp); /* DISPENTRY005 */
+               isc_async_run(resp->loop, resp_connected, resp);
                break;
 
        default: