]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1969. [bug] win32: the socket code was freeing the socket
authorMark Andrews <marka@isc.org>
Fri, 6 Jan 2006 01:32:08 +0000 (01:32 +0000)
committerMark Andrews <marka@isc.org>
Fri, 6 Jan 2006 01:32:08 +0000 (01:32 +0000)
                        structure too early. [RT #15776]

lib/isc/win32/socket.c

index cf6ee8baee79ab1be95f9cfac60bde32b20df9da..37cce8696ad01a2a60af3b86f90dc786f994f836 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: socket.c,v 1.41 2005/09/01 02:25:03 marka Exp $ */
+/* $Id: socket.c,v 1.42 2006/01/06 01:32:08 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
@@ -661,6 +661,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
        int i;
        WSAEVENT hEvent;
        int iEvent = -1;
+       isc_boolean_t dofree = ISC_FALSE;
 
        REQUIRE(evchange != NULL);
        /*  Make sure this is the right thread from which to delete the event */
@@ -693,8 +694,22 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
 
        /* Cleanup */
        WSACloseEvent(hEvent);
-       if (evchange->fd >= 0)
+
+       LOCK(&evchange->sock->lock);
+       if (evchange->sock->pending_close) {
+               evchange->sock->pending_close = 0;
                closesocket(evchange->fd);
+       }
+       if (evchange->sock->pending_recv == 0 &&
+           evchange->sock->pending_send == 0 &&
+           evchange->sock->pending_free) {
+               evchange->sock->pending_free = 0;
+               dofree = ISC_TRUE;
+       }
+       UNLOCK(&evchange->sock->lock);
+       if (dofree)
+               free_socket(&evchange->sock);
+
        evlist->max_event--;
        evlist->total_events--;
 
@@ -857,14 +872,12 @@ socket_event_delete(isc_socket_t *sock) {
        REQUIRE(sock != NULL);
        REQUIRE(sock->hEvent != NULL);
 
-       if (sock->hEvent != NULL) {
-               sock->wait_type = 0;
-               sock->pending_close = 1;
-               notify_eventlist(sock, sock->manager, EVENT_DELETE);
-               sock->hEvent = NULL;
-               sock->hAlert = NULL;
-               sock->evthread_id = 0;
-       }
+       sock->wait_type = 0;
+       sock->pending_close = 1;
+       notify_eventlist(sock, sock->manager, EVENT_DELETE);
+       sock->hEvent = NULL;
+       sock->hAlert = NULL;
+       sock->evthread_id = 0;
 }
 
 /*
@@ -878,17 +891,17 @@ void
 socket_close(isc_socket_t *sock) {
 
        REQUIRE(sock != NULL);
-       sock->pending_close = 1;
+
+       sock->pending_close = 0;
        if (sock->hEvent != NULL)
                socket_event_delete(sock);
-       else {
+       else
                closesocket(sock->fd);
-       }
+
        if (sock->iocp) {
                sock->iocp = 0;
                InterlockedDecrement(&iocp_total);
        }
-
 }
 
 /*
@@ -1666,7 +1679,7 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
        }
        dev->result = ISC_R_SUCCESS;
        status = DOIO_SOFT;
-done:
+ done:
        return (status);
 }
 
@@ -1696,7 +1709,8 @@ destroy_socket(isc_socket_t **sockp) {
 
        LOCK(&sock->lock);
        socket_close(sock);
-       if (sock->pending_recv != 0 || sock->pending_send != 0) {
+       if (sock->pending_recv != 0 || sock->pending_send != 0 ||
+           sock->pending_close != 0) {
                dofree = ISC_FALSE;
                sock->pending_free = 1;
        }
@@ -1893,6 +1907,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
 
        result = make_nonblock(sock->fd);
        if (result != ISC_R_SUCCESS) {
+               closesocket(sock->fd);
                free_socket(&sock);
                return (result);
        }
@@ -2560,8 +2575,11 @@ SocketIoThread(LPVOID ThreadContext) {
                                }
                                if (sock->pending_recv == 0 &&
                                    sock->pending_send == 0 &&
-                                   sock->pending_free)
+                                   sock->pending_close == 0 &&
+                                   sock->pending_free) {
+                                       sock->pending_free = 0;
                                        dofree = ISC_TRUE;
+                               }
                                UNLOCK(&sock->lock);
                                if (dofree)
                                        free_socket(&sock);