mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
do dns_request_t cancel processing through a control event to
ensure that dns_dispatch_removeresponse() is called from the correct task [RT #844]
This commit is contained in:
parent
4ce1248f09
commit
8126e45e8c
@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: events.h,v 1.36 2001/01/27 02:08:07 bwelling Exp $ */
|
/* $Id: events.h,v 1.37 2001/02/13 02:49:07 gson Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_EVENTS_H
|
#ifndef DNS_EVENTS_H
|
||||||
#define DNS_EVENTS_H 1
|
#define DNS_EVENTS_H 1
|
||||||
@ -59,6 +59,7 @@
|
|||||||
#define DNS_EVENT_LOOKUPDONE (ISC_EVENTCLASS_DNS + 30)
|
#define DNS_EVENT_LOOKUPDONE (ISC_EVENTCLASS_DNS + 30)
|
||||||
#define DNS_EVENT_QUERYABORTED (ISC_EVENTCLASS_DNS + 31)
|
#define DNS_EVENT_QUERYABORTED (ISC_EVENTCLASS_DNS + 31)
|
||||||
#define DNS_EVENT_DISPATCHCONTROL (ISC_EVENTCLASS_DNS + 32)
|
#define DNS_EVENT_DISPATCHCONTROL (ISC_EVENTCLASS_DNS + 32)
|
||||||
|
#define DNS_EVENT_REQUESTCONTROL (ISC_EVENTCLASS_DNS + 33)
|
||||||
|
|
||||||
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
|
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
|
||||||
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
|
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: request.c,v 1.55 2001/02/09 00:23:14 gson Exp $ */
|
/* $Id: request.c,v 1.56 2001/02/13 02:49:05 gson Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -83,7 +83,8 @@ struct dns_request {
|
|||||||
dns_requestmgr_t *requestmgr;
|
dns_requestmgr_t *requestmgr;
|
||||||
isc_buffer_t *tsig;
|
isc_buffer_t *tsig;
|
||||||
dns_tsigkey_t *tsigkey;
|
dns_tsigkey_t *tsigkey;
|
||||||
|
isc_event_t ctlevent;
|
||||||
|
isc_boolean_t canceling; /* ctlevent outstanding */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DNS_REQUEST_F_CONNECTING 0x0001
|
#define DNS_REQUEST_F_CONNECTING 0x0001
|
||||||
@ -120,6 +121,7 @@ static void req_sendevent(dns_request_t *request, isc_result_t result);
|
|||||||
static void req_cancel(dns_request_t *request);
|
static void req_cancel(dns_request_t *request);
|
||||||
static void req_destroy(dns_request_t *request);
|
static void req_destroy(dns_request_t *request);
|
||||||
static void req_log(int level, const char *fmt, ...);
|
static void req_log(int level, const char *fmt, ...);
|
||||||
|
static void do_cancel(isc_task_t *task, isc_event_t *event);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
*** Public
|
*** Public
|
||||||
@ -457,6 +459,10 @@ new_request(isc_mem_t *mctx, dns_request_t **requestp) {
|
|||||||
request->requestmgr = NULL;
|
request->requestmgr = NULL;
|
||||||
request->tsig = NULL;
|
request->tsig = NULL;
|
||||||
request->tsigkey = NULL;
|
request->tsigkey = NULL;
|
||||||
|
ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
|
||||||
|
DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
request->canceling = ISC_FALSE;
|
||||||
|
|
||||||
isc_mem_attach(mctx, &request->mctx);
|
isc_mem_attach(mctx, &request->mctx);
|
||||||
|
|
||||||
@ -998,6 +1004,40 @@ req_render(dns_message_t *message, isc_buffer_t **bufferp,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this request is no longer waiting for events,
|
||||||
|
* send the completion event. This will ultimately
|
||||||
|
* cause the request to be destroyed.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* 'request' is locked by the caller.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
send_if_done(dns_request_t *request, isc_result_t result) {
|
||||||
|
if (!DNS_REQUEST_CONNECTING(request) &&
|
||||||
|
!DNS_REQUEST_SENDING(request) &&
|
||||||
|
!request->canceling)
|
||||||
|
req_sendevent(request, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the control event.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
do_cancel(isc_task_t *task, isc_event_t *event) {
|
||||||
|
dns_request_t *request = event->ev_arg;
|
||||||
|
UNUSED(task);
|
||||||
|
INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
|
||||||
|
LOCK(&request->requestmgr->locks[request->hash]);
|
||||||
|
request->canceling = ISC_FALSE;
|
||||||
|
if (!DNS_REQUEST_CANCELED(request)) {
|
||||||
|
req_cancel(request);
|
||||||
|
send_if_done(request, ISC_R_CANCELED);
|
||||||
|
}
|
||||||
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||||
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_request_cancel(dns_request_t *request) {
|
dns_request_cancel(dns_request_t *request) {
|
||||||
REQUIRE(VALID_REQUEST(request));
|
REQUIRE(VALID_REQUEST(request));
|
||||||
@ -1007,11 +1047,10 @@ dns_request_cancel(dns_request_t *request) {
|
|||||||
REQUIRE(VALID_REQUEST(request));
|
REQUIRE(VALID_REQUEST(request));
|
||||||
|
|
||||||
LOCK(&request->requestmgr->locks[request->hash]);
|
LOCK(&request->requestmgr->locks[request->hash]);
|
||||||
if (!DNS_REQUEST_CANCELED(request)) {
|
if (!request->canceling) {
|
||||||
req_cancel(request);
|
isc_event_t *ev = &request->ctlevent;
|
||||||
if (!DNS_REQUEST_CONNECTING(request) &&
|
isc_task_send(request->event->ev_sender, &ev);
|
||||||
!DNS_REQUEST_SENDING(request))
|
request->canceling = ISC_TRUE;
|
||||||
req_sendevent(request, ISC_R_CANCELED);
|
|
||||||
}
|
}
|
||||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
@ -1057,13 +1096,19 @@ dns_request_destroy(dns_request_t **requestp) {
|
|||||||
req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
|
req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
|
||||||
|
|
||||||
LOCK(&request->requestmgr->locks[request->hash]);
|
LOCK(&request->requestmgr->locks[request->hash]);
|
||||||
LOCK(&request->requestmgr->lock);
|
|
||||||
ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
|
|
||||||
UNLOCK(&request->requestmgr->lock);
|
|
||||||
INSIST(!DNS_REQUEST_CONNECTING(request));
|
INSIST(!DNS_REQUEST_CONNECTING(request));
|
||||||
INSIST(!DNS_REQUEST_SENDING(request));
|
INSIST(!DNS_REQUEST_SENDING(request));
|
||||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These should have been cleaned up by req_cancel() before
|
||||||
|
* the completion event was sent.
|
||||||
|
*/
|
||||||
|
INSIST(!ISC_LINK_LINKED(request, link));
|
||||||
|
INSIST(request->dispentry == NULL);
|
||||||
|
INSIST(request->dispatch == NULL);
|
||||||
|
INSIST(request->timer == NULL);
|
||||||
|
|
||||||
req_destroy(request);
|
req_destroy(request);
|
||||||
|
|
||||||
*requestp = NULL;
|
*requestp = NULL;
|
||||||
@ -1093,9 +1138,9 @@ req_connected(isc_task_t *task, isc_event_t *event) {
|
|||||||
* Send delayed event.
|
* Send delayed event.
|
||||||
*/
|
*/
|
||||||
if (DNS_REQUEST_TIMEDOUT(request))
|
if (DNS_REQUEST_TIMEDOUT(request))
|
||||||
req_sendevent(request, ISC_R_TIMEDOUT);
|
send_if_done(request, ISC_R_TIMEDOUT);
|
||||||
else
|
else
|
||||||
req_sendevent(request, ISC_R_CANCELED);
|
send_if_done(request, ISC_R_CANCELED);
|
||||||
} else {
|
} else {
|
||||||
dns_dispatch_starttcp(request->dispatch);
|
dns_dispatch_starttcp(request->dispatch);
|
||||||
result = sevent->result;
|
result = sevent->result;
|
||||||
@ -1104,7 +1149,7 @@ req_connected(isc_task_t *task, isc_event_t *event) {
|
|||||||
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
req_cancel(request);
|
req_cancel(request);
|
||||||
req_sendevent(request, ISC_R_CANCELED);
|
send_if_done(request, ISC_R_CANCELED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||||
@ -1132,12 +1177,12 @@ req_senddone(isc_task_t *task, isc_event_t *event) {
|
|||||||
* Send delayed event.
|
* Send delayed event.
|
||||||
*/
|
*/
|
||||||
if (DNS_REQUEST_TIMEDOUT(request))
|
if (DNS_REQUEST_TIMEDOUT(request))
|
||||||
req_sendevent(request, ISC_R_TIMEDOUT);
|
send_if_done(request, ISC_R_TIMEDOUT);
|
||||||
else
|
else
|
||||||
req_sendevent(request, ISC_R_CANCELED);
|
send_if_done(request, ISC_R_CANCELED);
|
||||||
} else if (sevent->result != ISC_R_SUCCESS) {
|
} else if (sevent->result != ISC_R_SUCCESS) {
|
||||||
req_cancel(request);
|
req_cancel(request);
|
||||||
req_sendevent(request, ISC_R_CANCELED);
|
send_if_done(request, ISC_R_CANCELED);
|
||||||
}
|
}
|
||||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||||
|
|
||||||
@ -1184,7 +1229,7 @@ req_response(isc_task_t *task, isc_event_t *event) {
|
|||||||
/*
|
/*
|
||||||
* Send completion event.
|
* Send completion event.
|
||||||
*/
|
*/
|
||||||
req_sendevent(request, result);
|
send_if_done(request, result);
|
||||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1200,9 +1245,7 @@ req_timeout(isc_task_t *task, isc_event_t *event) {
|
|||||||
LOCK(&request->requestmgr->locks[request->hash]);
|
LOCK(&request->requestmgr->locks[request->hash]);
|
||||||
request->flags |= DNS_REQUEST_F_TIMEDOUT;
|
request->flags |= DNS_REQUEST_F_TIMEDOUT;
|
||||||
req_cancel(request);
|
req_cancel(request);
|
||||||
if (!DNS_REQUEST_CONNECTING(request) &&
|
send_if_done(request, ISC_R_TIMEDOUT);
|
||||||
!DNS_REQUEST_SENDING(request))
|
|
||||||
req_sendevent(request, ISC_R_TIMEDOUT);
|
|
||||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||||
isc_event_free(&event);
|
isc_event_free(&event);
|
||||||
}
|
}
|
||||||
@ -1269,6 +1312,15 @@ req_cancel(dns_request_t *request) {
|
|||||||
*/
|
*/
|
||||||
request->flags |= DNS_REQUEST_F_CANCELED;
|
request->flags |= DNS_REQUEST_F_CANCELED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unlink from the manager here so that it will not try
|
||||||
|
* to cancel us after we have already sent the completion
|
||||||
|
* event.
|
||||||
|
*/
|
||||||
|
LOCK(&request->requestmgr->lock);
|
||||||
|
ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
|
||||||
|
UNLOCK(&request->requestmgr->lock);
|
||||||
|
|
||||||
if (request->timer != NULL)
|
if (request->timer != NULL)
|
||||||
isc_timer_detach(&request->timer);
|
isc_timer_detach(&request->timer);
|
||||||
if (request->dispentry != NULL)
|
if (request->dispentry != NULL)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user