2
0
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:
Andreas Gustafsson 2001-02-13 02:49:07 +00:00
parent 4ce1248f09
commit 8126e45e8c
2 changed files with 74 additions and 21 deletions

View File

@ -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)

View File

@ -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)