Commit 96ab2529 authored by David Lawrence's avatar David Lawrence
Browse files

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.
parent 9a68d613
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 {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment