307. [bug] When canceling a query, the resolver didn't check for
isc_socket_sendto() calls that did not yet have their completion events posted, so it could (rarely) end up destroying the query context and then want to use it again when the send event posted, triggering an assertion as it tried to cancel an already-canceled query. (RT #77) ... so now the resolver counts the number of outstanding isc_socket_sendto()s and only destroys the query context when there are no more.
This commit is contained in:
14
CHANGES
14
CHANGES
@@ -1,6 +1,14 @@
|
||||
306. [bug] Reading HMAC-MD5 private key files didn't work.
|
||||
307. [bug] When canceling a query, the resolver didn't check for
|
||||
isc_socket_sendto() calls that did not yet have their
|
||||
completion events posted, so it could (rarely) end up
|
||||
destroying the query context and then want to use
|
||||
it again when the send event posted, triggering an
|
||||
assertion as it tried to cancel an already-canceled
|
||||
query. (RT #77)
|
||||
|
||||
305. [bug] When reloading the server with a config file
|
||||
306. [bug] Reading HMAC-MD5 private key files didn't work.
|
||||
|
||||
305. [bug] When reloading the server with a config file
|
||||
containing a syntax error, it could catch an
|
||||
assertion failure trying to perform zone
|
||||
maintenance on tentatively created zones whose
|
||||
@@ -11,7 +19,7 @@
|
||||
are listed in resolv.conf, silently ignore them
|
||||
instead of returning failure.
|
||||
|
||||
303. [bug] add additional sanity checks to differentiate a AXFR
|
||||
303. [bug] Add additional sanity checks to differentiate a AXFR
|
||||
response vs a IXFR response. (RT #157)
|
||||
|
||||
302. [bug] In dig, host, and nslookup, MXNAME should be large
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: resolver.c,v 1.140 2000/06/28 16:30:29 explorer Exp $ */
|
||||
/* $Id: resolver.c,v 1.141 2000/07/04 01:19:20 tale Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -117,6 +117,7 @@ typedef struct query {
|
||||
dns_tsigkey_t *tsigkey;
|
||||
unsigned int options;
|
||||
unsigned int attributes;
|
||||
unsigned int sends;
|
||||
unsigned char data[512];
|
||||
} resquery_t;
|
||||
|
||||
@@ -131,6 +132,7 @@ typedef struct query {
|
||||
RESQUERY_ATTR_CONNECTING) != 0)
|
||||
#define RESQUERY_CANCELED(q) (((q)->attributes & \
|
||||
RESQUERY_ATTR_CANCELED) != 0)
|
||||
#define RESQUERY_SENDING(q) ((q)->sends > 0)
|
||||
|
||||
typedef enum {
|
||||
fetchstate_init = 0, /* Start event has not run yet. */
|
||||
@@ -337,7 +339,7 @@ resquery_destroy(resquery_t **queryp) {
|
||||
INSIST(query->tcpsocket == NULL);
|
||||
|
||||
query->magic = 0;
|
||||
isc_mem_put(query->mctx, query, sizeof *query);
|
||||
isc_mem_put(query->mctx, query, sizeof(*query));
|
||||
*queryp = NULL;
|
||||
}
|
||||
|
||||
@@ -393,26 +395,39 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
|
||||
|
||||
if (query->dispentry != NULL)
|
||||
dns_dispatch_removeresponse(&query->dispentry, deventp);
|
||||
|
||||
ISC_LIST_UNLINK(fctx->queries, query, link);
|
||||
|
||||
if (query->tsig != NULL)
|
||||
isc_buffer_free(&query->tsig);
|
||||
if (RESQUERY_CONNECTING(query)) {
|
||||
|
||||
/*
|
||||
* Check for any outstanding socket events. If they exist, cancel
|
||||
* them and let the event handlers finish the cleanup. The resolver
|
||||
* only needs to worry about managing the connect and send events;
|
||||
* the dispatcher manages the recv events.
|
||||
*/
|
||||
if (RESQUERY_CONNECTING(query))
|
||||
/*
|
||||
* Cancel the connect.
|
||||
*/
|
||||
isc_socket_cancel(query->tcpsocket, NULL,
|
||||
ISC_SOCKCANCEL_CONNECT);
|
||||
}
|
||||
else if (RESQUERY_SENDING(query))
|
||||
/*
|
||||
* Cancel the pending send.
|
||||
*/
|
||||
isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
|
||||
NULL, ISC_SOCKCANCEL_SEND);
|
||||
|
||||
if (query->dispatch != NULL)
|
||||
dns_dispatch_detach(&query->dispatch);
|
||||
|
||||
if (!RESQUERY_CONNECTING(query)) {
|
||||
if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
|
||||
/*
|
||||
* It's safe to destroy the query now.
|
||||
*/
|
||||
resquery_destroy(&query);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -536,9 +551,24 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
INSIST(RESQUERY_SENDING(query));
|
||||
|
||||
query->sends--;
|
||||
|
||||
if (sevent->result != ISC_R_SUCCESS)
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
|
||||
if (RESQUERY_CANCELED(query)) {
|
||||
if (query->sends == 0) {
|
||||
/*
|
||||
* This query was canceled while the
|
||||
* isc_socket_sendto() was in progress.
|
||||
*/
|
||||
if (query->tcpsocket != NULL)
|
||||
isc_socket_detach(&query->tcpsocket);
|
||||
resquery_destroy(&query);
|
||||
}
|
||||
} else
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
@@ -654,6 +684,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
query->mctx = res->mctx;
|
||||
query->options = options;
|
||||
query->attributes = 0;
|
||||
query->sends = 0;
|
||||
/*
|
||||
* Note that the caller MUST guarantee that 'addrinfo' will remain
|
||||
* valid until this query is canceled.
|
||||
@@ -987,6 +1018,7 @@ resquery_send(resquery_t *query) {
|
||||
query, address, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_message;
|
||||
query->sends++;
|
||||
QTRACE("sent");
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
@@ -1075,7 +1107,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fetchctx_t *fctx = query->fctx;
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
fctx_cancelquery(&query, NULL, NULL,
|
||||
ISC_FALSE);
|
||||
fctx_done(fctx, result);
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user