]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a race in fctx_cancelquery.
authorWitold Kręcicki <wpk@culm.net>
Wed, 13 Feb 2019 10:10:31 +0000 (11:10 +0100)
committerWitold Kręcicki <wpk@culm.net>
Tue, 12 Mar 2019 17:42:35 +0000 (18:42 +0100)
When sending an udp query (resquery_send) we first issue an asynchronous
isc_socket_connect and increment query->connects, then isc_socket_sendto2
and increment query->sends.
If we happen to cancel this query (fctx_cancelquery) we need to cancel
all operations we might have issued on this socket. If we are under very high
load the callback from isc_socket_connect (resquery_udpconnected) might have
not yet been fired. In this case we only cancel the CONNECT event on socket,
and ignore the SEND that's waiting there (as there is an `else if`).
Then we call dns_dispatch_removeresponse which kills the dispatcher socket
and calls isc_socket_close - but if system is under very high load, the send
we issued earlier might still not be complete - which triggers an assertion
because we're trying to close a socket that's still in use.

The fix is to always check if we have incomplete sends on the socket and cancel
them if we do.

lib/dns/resolver.c

index 86dad48ebc9628e74d800988d6257076861de4ea..184cba1036e61e3d197c05ba04ef63a0c98d064f 100644 (file)
@@ -1321,7 +1321,8 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
                                isc_socket_cancel(sock, NULL,
                                                  ISC_SOCKCANCEL_CONNECT);
                }
-       } else if (RESQUERY_SENDING(query)) {
+       }
+       if (RESQUERY_SENDING(query)) {
                /*
                 * Cancel the pending send.
                 */