]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2220. [bug] win32: Address a race condition in final shutdown of
authorMark Andrews <marka@isc.org>
Tue, 28 Aug 2007 00:42:27 +0000 (00:42 +0000)
committerMark Andrews <marka@isc.org>
Tue, 28 Aug 2007 00:42:27 +0000 (00:42 +0000)
                        the Windows socket code. [RT #17028]

CHANGES
lib/isc/win32/socket.c

diff --git a/CHANGES b/CHANGES
index fec6c77c0a32ad7645b99a9c3448fe48463cef0e..12f4dde2bf4d36286352e15e62d31b2e861091fe 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+2220.  [bug]           win32: Address a race condition in final shutdown of
+                       the Windows socket code. [RT #17028]
+                       
 2218.  [bug]           Remove unnecessary REQUIRE from dns_validator_create().
                        [RT #16976]
 
index 72f7a7964f45617868c54a8c999982c382cd318e..6cdb1c0b910340defe043846313951baaeed32c0 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: socket.c,v 1.5.2.33 2007/06/18 03:30:31 marka Exp $ */
+/* $Id: socket.c,v 1.5.2.34 2007/08/28 00:42:27 marka Exp $ */
 
 /* This code has been rewritten to take advantage of Windows Sockets
  * I/O Completion Ports and Events. I/O Completion Ports is ONLY
@@ -650,10 +650,11 @@ socket_eventlist_add(event_change_t *evchange, sock_event_list *evlist,
 
 /*
  * Note that the eventLock is locked before calling this function.
- * All Events and associated sockets are closed here.
  */
 isc_boolean_t
-socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
+socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
+                       isc_socketmgr_t *manager)
+{
        int i;
        WSAEVENT hEvent;
        int iEvent = -1;
@@ -700,12 +701,16 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
            evchange->sock->pending_send == 0 &&
            evchange->sock->pending_free) {
                evchange->sock->pending_free = 0;
+               ISC_LIST_UNLINK(manager->socklist, evchange->sock, link);
                dofree = ISC_TRUE;
        }
        UNLOCK(&evchange->sock->lock);
        if (dofree)
                free_socket(&evchange->sock);
 
+       if (ISC_LIST_EMPTY(manager->socklist))
+               SIGNAL(&manager->shutdown_ok);
+
        evlist->max_event--;
        evlist->total_events--;
 
@@ -744,7 +749,8 @@ process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) {
                next = ISC_LIST_NEXT(evchange, link);
                del = ISC_FALSE;
                if (evchange->action == EVENT_DELETE) {
-                       del = socket_eventlist_delete(evchange, evlist);
+                       del = socket_eventlist_delete(evchange, evlist,
+                                                     manager);
 
                        /*
                         * Delete only if this thread's socket list was
@@ -1726,8 +1732,8 @@ destroy_socket(isc_socket_t **sockp) {
            sock->pending_close != 0) {
                dofree = ISC_FALSE;
                sock->pending_free = 1;
-       }
-       ISC_LIST_UNLINK(manager->socklist, sock, link);
+       } else
+               ISC_LIST_UNLINK(manager->socklist, sock, link);
        UNLOCK(&sock->lock);
 
        if (ISC_LIST_EMPTY(manager->socklist))
@@ -2581,8 +2587,15 @@ SocketIoThread(LPVOID ThreadContext) {
                                        dofree = ISC_TRUE;
                                }
                                UNLOCK(&sock->lock);
-                               if (dofree)
+                               if (dofree) {
+                                       LOCK(&manager->lock);
+                                       ISC_LIST_UNLINK(manager->socklist,
+                                                       sock, link);
                                        free_socket(&sock);
+                                       if (ISC_LIST_EMPTY(manager->socklist))
+                                               SIGNAL(&manager->shutdown_ok);
+                                       UNLOCK(&manager->lock);
+                               }
                                if (lpo != NULL)
                                        HeapFree(hHeapHandle, 0, lpo);
                                continue;