From: Tatuya JINMEI 神明達哉 Date: Wed, 4 Sep 2002 02:26:13 +0000 (+0000) Subject: fixed a bug that named crashes with an assertion failure on exit when sharing X-Git-Tag: v9.2.3rc1~104^2~357 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=e992af4209b737f511b6f2fad3ddb7bdfc17b9ae;p=thirdparty%2Fbind9.git fixed a bug that named crashes with an assertion failure on exit when sharing the same port for listening and querying, and changing listening addresses several times. [RT# 3509] additionally, + limited the canceled socket tasks in dispatch.c + made dns_dispatch_changeattributes() care about the NOLISTEN mask + described side effects of dns_dispatch_changeattributes() in its description comment --- diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 5e6bf9ba5ae..a54244d3927 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.109 2002/07/29 01:03:24 marka Exp $ */ +/* $Id: dispatch.c,v 1.110 2002/09/04 02:26:12 jinmei Exp $ */ #include @@ -501,12 +501,7 @@ allocate_event(dns_dispatch_t *disp) { * * If I/O result == CANCELED or error, free the buffer. * - * If query: - * if no listeners: free the buffer, restart. - * if listener: allocate event, fill in details. - * If cannot allocate, free buffer, restart. - * if rq event queue is not empty, queue. else, send. - * restart. + * If query, free the buffer, restart. * * If response: * Allocate event, fill in details. @@ -544,7 +539,12 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { "got packet: requests %d, buffers %d, recvs %d", disp->requests, disp->mgr->buffers, disp->recv_pending); - if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) { + if (ev->ev_type == ISC_SOCKEVENT_RECVDONE) { + /* + * Unless the receive event was imported from a listening + * interface, in which case the event type is + * DNS_EVENT_IMPORTRECVDONE, receive operation must be pending. + */ INSIST(disp->recv_pending != 0); disp->recv_pending = 0; } @@ -687,20 +687,15 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { /* * General flow: * - * If I/O result == CANCELED, EOF, or error, free the buffer - * and notify everyone as the various queues drain. + * If I/O result == CANCELED, EOF, or error, notify everyone as the + * various queues drain. * - * If query: - * if no listeners: free the buffer, restart. - * if listener: allocate event, fill in details. - * If cannot allocate, free buffer, restart. - * if rq event queue is not empty, queue. else, send. - * restart. + * If query, restart. * * If response: * Allocate event, fill in details. - * If cannot allocate, free buffer, restart. - * find target. If not found, free buffer, restart. + * If cannot allocate, restart. + * find target. If not found, restart. * if event queue is not empty, queue. else, send. * restart. */ @@ -773,7 +768,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { * free the event *before* calling destroy_disp(). */ isc_event_free(&ev_in); - + disp->shutting_down = 1; disp->shutdown_why = tcpmsg->result; @@ -1590,7 +1585,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, { disp->attributes |= DNS_DISPATCHATTR_NOLISTEN; if (disp->recv_pending != 0) - isc_socket_cancel(disp->socket, NULL, + isc_socket_cancel(disp->socket, disp->task, ISC_SOCKCANCEL_RECV); } @@ -1728,7 +1723,7 @@ dns_dispatch_detach(dns_dispatch_t **dispp) { killit = ISC_FALSE; if (disp->refcount == 0) { if (disp->recv_pending > 0) - isc_socket_cancel(disp->socket, NULL, + isc_socket_cancel(disp->socket, disp->task, ISC_SOCKCANCEL_RECV); disp->shutting_down = 1; } @@ -1891,7 +1886,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, killit = ISC_FALSE; if (disp->refcount == 0) { if (disp->recv_pending > 0) - isc_socket_cancel(disp->socket, NULL, + isc_socket_cancel(disp->socket, disp->task, ISC_SOCKCANCEL_RECV); disp->shutting_down = 1; } @@ -2057,11 +2052,19 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp, LOCK(&disp->lock); - if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 && - (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) - { - disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN; - startrecv(disp); + if ((mask & DNS_DISPATCHATTR_NOLISTEN) != 0) { + if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 && + (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) { + disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN; + startrecv(disp); + } else if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) + == 0 && + (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) { + disp->attributes |= DNS_DISPATCHATTR_NOLISTEN; + if (disp->recv_pending != 0) + isc_socket_cancel(disp->socket, disp->task, + ISC_SOCKCANCEL_RECV); + } } disp->attributes &= ~mask; @@ -2083,7 +2086,7 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) { INSIST(sevent->n <= disp->mgr->buffersize); newsevent = (isc_socketevent_t *) isc_event_allocate(disp->mgr->mctx, NULL, - ISC_SOCKEVENT_RECVDONE, udp_recv, + DNS_EVENT_IMPORTRECVDONE, udp_recv, disp, sizeof(isc_socketevent_t)); if (newsevent == NULL) return; diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index 89615afcf20..a3ed03968ce 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.h,v 1.45 2001/04/30 18:09:28 gson Exp $ */ +/* $Id: dispatch.h,v 1.46 2002/09/04 02:26:13 jinmei Exp $ */ #ifndef DNS_DISPATCH_H #define DNS_DISPATCH_H 1 @@ -391,6 +391,11 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp, * * new = (old & ~mask) | (attributes & mask) * + * This function has a side effect when DNS_DISPATCHATTR_NOLISTEN changes. + * When the flag becomes off, the dispatch will start receiving on the + * corresponding socket. When the flag becomes on, receive events on the + * corresponding socket will be canceled. + * * Requires: * disp is valid. * diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index f7d85236332..d44dbd2f453 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: events.h,v 1.39 2001/09/21 14:00:06 marka Exp $ */ +/* $Id: events.h,v 1.40 2002/09/04 02:26:13 jinmei Exp $ */ #ifndef DNS_EVENTS_H #define DNS_EVENTS_H 1 @@ -61,6 +61,7 @@ #define DNS_EVENT_DISPATCHCONTROL (ISC_EVENTCLASS_DNS + 32) #define DNS_EVENT_REQUESTCONTROL (ISC_EVENTCLASS_DNS + 33) #define DNS_EVENT_DUMPQUANTUM (ISC_EVENTCLASS_DNS + 34) +#define DNS_EVENT_IMPORTRECVDONE (ISC_EVENTCLASS_DNS + 35) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)