]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
fixed a bug that named crashes with an assertion failure on exit when sharing
authorTatuya JINMEI 神明達哉 <jinmei@isc.org>
Wed, 4 Sep 2002 02:26:13 +0000 (02:26 +0000)
committerTatuya JINMEI 神明達哉 <jinmei@isc.org>
Wed, 4 Sep 2002 02:26:13 +0000 (02:26 +0000)
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

lib/dns/dispatch.c
lib/dns/include/dns/dispatch.h
lib/dns/include/dns/events.h

index 5e6bf9ba5aed637d956354ad9e1109c33fa190f6..a54244d392772647c42f7807bc09f6e0e02b1ba1 100644 (file)
@@ -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 <config.h>
 
@@ -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;
index 89615afcf200ae7b0781d01c0eb15cd736ef8c70..a3ed03968ce5c40afae03f6393a73d82178a5dc9 100644 (file)
@@ -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.
  *
index f7d85236332a34ca7449d7c2ad614040e5927056..d44dbd2f453fead369bf020fc685385ac771bc9c 100644 (file)
@@ -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)