]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2412. [bug] win32: address a resourse leak. [RT #18374]
authorMark Andrews <marka@isc.org>
Fri, 8 Aug 2008 05:06:49 +0000 (05:06 +0000)
committerMark Andrews <marka@isc.org>
Fri, 8 Aug 2008 05:06:49 +0000 (05:06 +0000)
CHANGES
bin/named/statschannel.c
lib/isc/httpd.c
lib/isc/include/isc/httpd.h
lib/isc/include/isc/msgs.h
lib/isc/win32/errno2result.c
lib/isc/win32/net.c
lib/isc/win32/socket.c

diff --git a/CHANGES b/CHANGES
index 590c984e10298e8a1732d5734ce9bd79ac5a3d26..9b908ff6527efa7a5e3750072be036359b41870d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+2412.  [bug]           win32: address a resourse leak. [RT #18374]
+
 2411.  [bug]           Allow using a larger number of sockets than FD_SETSIZE
                        for select().  To enable this, set ISC_SOCKET_MAXSOCKETS
                        at compilation time.  [RT #18433]
index 0e0a43ec6740971aded8651bc24b200f17d2b1fe..6dc4fc643f6fbb4b53be4f2567ef837a7f97fc9e 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: statschannel.c,v 1.13 2008/07/23 23:27:54 marka Exp $ */
+/* $Id: statschannel.c,v 1.14 2008/08/08 05:06:49 marka Exp $ */
 
 /*! \file */
 
@@ -110,7 +110,7 @@ set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
 }
 
 static void
-init_desc() {
+init_desc(void) {
        int i;
 
        /* Initialize name server statistics */
index 96c78a8fd708458c8b195733fec72221460901a7..fa313253b3e93e4f1c48b9d84e14a9668ecc1ab8 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: httpd.c,v 1.15 2008/01/18 23:46:58 tbox Exp $ */
+/* $Id: httpd.c,v 1.16 2008/08/08 05:06:49 marka Exp $ */
 
 /*! \file */
 
+#include <config.h>
+
 #include <isc/buffer.h>
 #include <isc/httpd.h>
 #include <isc/mem.h>
index 95aa0d727e35a6a2fcf0b1b768e91934e0925359..ba7f900198e464e8cca15512796f4a245191d5bb 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: httpd.h,v 1.8 2008/01/17 23:47:00 tbox Exp $ */
+/* $Id: httpd.h,v 1.9 2008/08/08 05:06:49 marka Exp $ */
 
 #ifndef ISC_HTTPD_H
 #define ISC_HTTPD_H 1
@@ -47,7 +47,7 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdp);
 
 isc_result_t
 isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
-                   isc_httpdaction_t func, void *arg);
+                   isc_httpdaction_t *func, void *arg);
 
 isc_result_t
 isc_httpd_response(isc_httpd_t *httpd);
index 88b93a52debdfe04629d213e85dd362a755014f4..88505a5465e7139d3a62d8d40aa0c1399e24444b 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: msgs.h,v 1.15 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: msgs.h,v 1.16 2008/08/08 05:06:49 marka Exp $ */
 
 #ifndef ISC_MSGS_H
 #define ISC_MSGS_H 1
 #define ISC_MSG_ACCEPTRETURNED 1418 /*%< accept() returned %d/%s */
 #define ISC_MSG_TOOMANYFDS     1419 /*%< %s: too many open file descriptors */
 #define ISC_MSG_ZEROPORT       1420 /*%< dropping source port zero packet */
-#define ISC_MSG_FILTER        1420 /*%< setsockopt(SO_ACCEPTFILTER): %s */
+#define ISC_MSG_FILTER        1421 /*%< setsockopt(SO_ACCEPTFILTER): %s */
+
+#define ISC_MSG_TOOMANYHANDLES 1422 /*%< %s: too many open WSA event handles: %s */
+
 
 #define ISC_MSG_AWAKE         1502 /*%< "awake" */
 #define ISC_MSG_WORKING               1503 /*%< "working" */
index b5e4dd833cb60bbf9587b7201d77566cc442d312..333c7c1591caec89500a73576ad22c917c4b0880 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: errno2result.c,v 1.14 2007/06/19 23:47:19 tbox Exp $ */
+/* $Id: errno2result.c,v 1.15 2008/08/08 05:06:49 marka Exp $ */
 
 #include <config.h>
 
@@ -61,14 +61,24 @@ isc__errno2resultx(int posixerrno, const char *file, int line) {
        case EMFILE:
        case WSAEMFILE:
                return (ISC_R_TOOMANYOPENFILES);
-       case ERROR_OPERATION_ABORTED:
-               return (ISC_R_CONNECTIONRESET);
-       case ERROR_PORT_UNREACHABLE:
-               return (ISC_R_HOSTUNREACH);
+       case ERROR_CANCELLED:
+               return (ISC_R_CANCELED);
+       case ERROR_CONNECTION_REFUSED:
+               return (ISC_R_CONNREFUSED);
+       case ERROR_CONNECTION_INVALID:
+               return (ISC_R_NOTCONNECTED);
        case ERROR_HOST_UNREACHABLE:
                return (ISC_R_HOSTUNREACH);
        case ERROR_NETWORK_UNREACHABLE:
                return (ISC_R_NETUNREACH);
+       case ERROR_NO_NETWORK:
+               return (ISC_R_NETUNREACH);
+       case ERROR_OPERATION_ABORTED:
+               return (ISC_R_CONNECTIONRESET);
+       case ERROR_PORT_UNREACHABLE:
+               return (ISC_R_HOSTUNREACH);
+       case ERROR_REQUEST_ABORTED:
+               return (ISC_R_CONNECTIONRESET);
        case WSAEADDRNOTAVAIL:
                return (ISC_R_ADDRNOTAVAIL);
        case WSAEHOSTUNREACH:
index 5647c424bca162ae1ddc41cfc6bd6e9342bc3e50..3785f8abdf1b08f68ea1ba86524f4bb1e8ff3121 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: net.c,v 1.17 2008/07/01 03:55:10 each Exp $ */
+/* $Id: net.c,v 1.18 2008/08/08 05:06:49 marka Exp $ */
 
 #include <config.h>
 
@@ -242,7 +242,8 @@ try_ipv6pktinfo(void) {
        optname = IPV6_PKTINFO;
 #endif
        on = 1;
-       if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) {
+       if (setsockopt(s, IPPROTO_IPV6, optname, (const char *) &on,
+                      sizeof(on)) < 0) {
                ipv6pktinfo_result = ISC_R_NOTFOUND;
                goto close;
        }
index ed6132eeffe6b7c2491ca1452f9ac8c1e4c4361b..b1edd845f944014138d2e860b7eb97288c9e3158 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: socket.c,v 1.62 2008/07/24 09:50:21 fdupont Exp $ */
+/* $Id: socket.c,v 1.63 2008/08/08 05:06:49 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
 #define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0)
 
 #define DOIO_SUCCESS     0       /* i/o ok, event sent */
-#define DOIO_SOFT           1       /* i/o ok, soft error, no event sent */
-#define DOIO_HARD           2       /* i/o error, event sent */
-#define DOIO_EOF             3       /* EOF, no event sent */
+#define DOIO_SOFT        1       /* i/o ok, soft error, no event sent */
+#define DOIO_HARD        2       /* i/o error, event sent */
+#define DOIO_EOF         3       /* EOF, no event sent */
 #define DOIO_PENDING     4       /* status when i/o is in process */
 
 #define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
@@ -194,8 +194,8 @@ struct msghdr {
        int     msg_totallen;           /* total length of this message */
 } msghdr;
 
-/*%
- * The size to raise the recieve buffer to.
+/*
+ * The size to raise the receive buffer to.
  */
 #define RCVBUFSIZE (32*1024)
 
@@ -540,10 +540,13 @@ iocompletionport_update(isc_socket_t *sock) {
        }
 }
 
-void
+isc_result_t
 socket_event_minit(sock_event_list *evlist) {
        BOOL bReset;
        int i;
+       int stat;
+       WSAEVENT hEvent;
+       char strbuf[ISC_STRERRORSIZE];
 
        REQUIRE(evlist != NULL);
        /* Initialize the Event List */
@@ -554,9 +557,28 @@ socket_event_minit(sock_event_list *evlist) {
                evlist->aEventList[i] = (WSAEVENT) 0;
        }
 
-       evlist->aEventList[0] = WSACreateEvent();
+       /*
+        * The event list needs its own event handle so that when we
+        * want to change the list the event loop can be notified.
+        */
+       hEvent = WSACreateEvent();
+       if (hEvent == WSA_INVALID_EVENT) {
+               stat = WSAGetLastError();
+               isc__strerror(stat, strbuf, sizeof(strbuf));
+               isc_log_iwrite(isc_lctx,
+                               ISC_LOGCATEGORY_GENERAL,
+                               ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+                               isc_msgcat, ISC_MSGSET_SOCKET,
+                               ISC_MSG_TOOMANYHANDLES,
+                               "%s: too many open WSA event handles: %s",
+                               "WSACreateEvent", strbuf);
+               return (ISC_R_UNEXPECTED);
+       }
+
+       evlist->aEventList[0] = hEvent;
        (evlist->max_event)++;
        bReset = WSAResetEvent(evlist->aEventList[0]);
+       return (ISC_R_SUCCESS);
 }
 /*
  * Event Thread Initialization
@@ -569,7 +591,10 @@ event_thread_create(events_thread_t **evthreadp, isc_socketmgr_t *manager) {
        REQUIRE(evthreadp != NULL && *evthreadp == NULL);
 
        evthread = isc_mem_get(manager->mctx, sizeof(*evthread));
-       socket_event_minit(&evthread->sockev_list);
+       if (socket_event_minit(&evthread->sockev_list) != ISC_R_SUCCESS) {
+               isc_mem_put(manager->mctx, evthread, sizeof(*evthread));
+               return (ISC_R_UNEXPECTED);
+       }
        ISC_LINK_INIT(evthread, link);
        evthread->manager = manager;
 
@@ -645,21 +670,25 @@ socket_eventlist_add(event_change_t *evchange, sock_event_list *evlist,
                locate_available_thread(manager);
                return (ISC_FALSE);
        }
-
+       /*
+        * Lock the socket before updating
+        */
+       LOCK(&sock->lock);
        evlist->aSockList[max_event] = sock;
        evlist->aEventList[max_event] = sock->hEvent;
        evlist->max_event++;
        evlist->total_events++;
        sock->hAlert = evlist->aEventList[0];
        sock->evthread_id = GetCurrentThreadId();
+       UNLOCK(&sock->lock);
        return (ISC_TRUE);
 }
 
 /*
- * Note that the eventLock is locked before calling this function.
+ * Delete the event from the list
  */
 isc_boolean_t
-socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
+eventlist_event_delete(isc_socket_t *sock, sock_event_list *evlist,
                        isc_socketmgr_t *manager)
 {
        int i;
@@ -667,14 +696,11 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
        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 */
-       if (evchange->evthread_id != GetCurrentThreadId())
-               return (ISC_FALSE);
-
+       REQUIRE(sock != NULL);
        REQUIRE(evlist != NULL);
-       REQUIRE(evchange->hEvent != NULL);
-       hEvent = evchange->hEvent;
+       REQUIRE(manager != NULL);
+       REQUIRE(sock->hEvent != NULL);
+       hEvent = sock->hEvent;
 
        /* Find the Event */
        for (i = 1; i < evlist->max_event; i++) {
@@ -684,7 +710,10 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
                }
        }
 
-       /* Actual event start at 1 */
+       /*
+        * Actual event start at 1
+        * event at 0 is the thread wakeup
+        */
        if (iEvent < 1)
                return (ISC_FALSE);
 
@@ -699,21 +728,25 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
        /* Cleanup */
        WSACloseEvent(hEvent);
 
-       LOCK(&evchange->sock->lock);
-       if (evchange->sock->pending_close) {
-               evchange->sock->pending_close = 0;
-               closesocket(evchange->fd);
+       LOCK(&sock->lock);
+       sock->hEvent = NULL;
+       sock->hAlert = NULL;
+       sock->wait_type = 0;
+
+       if (sock->pending_close) {
+               sock->pending_close = 0;
+               closesocket(sock->fd);
        }
-       if (evchange->sock->pending_recv == 0 &&
-           evchange->sock->pending_send == 0 &&
-           evchange->sock->pending_free) {
-               evchange->sock->pending_free = 0;
-               ISC_LIST_UNLINK(manager->socklist, evchange->sock, link);
+       if (sock->pending_recv == 0 &&
+           sock->pending_send == 0 &&
+           sock->pending_free) {
+               sock->pending_free = 0;
+               ISC_LIST_UNLINK(manager->socklist, sock, link);
                dofree = ISC_TRUE;
        }
-       UNLOCK(&evchange->sock->lock);
+       UNLOCK(&sock->lock);
        if (dofree)
-               free_socket(&evchange->sock);
+               free_socket(&sock);
 
        if (ISC_LIST_EMPTY(manager->socklist))
                SIGNAL(&manager->shutdown_ok);
@@ -724,6 +757,21 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
        return (ISC_TRUE);
 }
 
+/*
+ * Note that the eventLock is locked before calling this function.
+ */
+isc_boolean_t
+socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
+                       isc_socketmgr_t *manager)
+{
+
+       REQUIRE(evchange != NULL);
+       /*  Make sure this is the right thread from which to delete the event */
+       if (evchange->evthread_id != GetCurrentThreadId())
+               return (ISC_FALSE);
+
+       return (eventlist_event_delete(evchange->sock, evlist, manager));
+}
 /*
  * Get the event changes off of the list and apply the
  * requested changes. The manager lock is taken out at
@@ -850,10 +898,13 @@ socket_event_add(isc_socket_t *sock, long type) {
        if (hEvent == WSA_INVALID_EVENT) {
                stat = WSAGetLastError();
                isc__strerror(stat, strbuf, sizeof(strbuf));
-               msg = isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
-                                    ISC_MSG_FAILED, "failed"),
-               UNEXPECTED_ERROR(__FILE__, __LINE__, "WSACreateEvent: %s: %s",
-                                msg, strbuf);
+               isc_log_iwrite(isc_lctx,
+                               ISC_LOGCATEGORY_GENERAL,
+                               ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+                               isc_msgcat, ISC_MSGSET_SOCKET,
+                               ISC_MSG_TOOMANYHANDLES,
+                               "%s: too many open WSA event handles: %s",
+                               "WSACreateEvent", strbuf);
                return (ISC_R_UNEXPECTED);
        }
        if (WSAEventSelect(sock->fd, hEvent, type) != 0) {
@@ -873,7 +924,11 @@ socket_event_add(isc_socket_t *sock, long type) {
 }
 
 /*
- * Note that the socket is not locked before calling this function
+ * Note that the socket is locked before calling this function
+ * Note also that we cannot close the socket here or event handle being
+ * used since the event is being waited upon and any change to either
+ * will signal the change. The notify_eventlist will take care of
+ * these details.
  */
 void
 socket_event_delete(isc_socket_t *sock) {
@@ -884,8 +939,6 @@ socket_event_delete(isc_socket_t *sock) {
        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;
 }
 
@@ -895,6 +948,7 @@ socket_event_delete(isc_socket_t *sock) {
  * with an event, otherwise the WSAWaitForMultipleEvents
  * may fail due to the fact that the the Wait should not
  * be running while closing an event or a socket.
+ * The socket is locked before calling this function
  */
 void
 socket_close(isc_socket_t *sock) {
@@ -958,7 +1012,7 @@ internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
        int total_sent;
 
        *Error = 0;
-       Result = WSASendTo((SOCKET) sock->fd, messagehdr->msg_iov,
+       Result = WSASendTo(sock->fd, messagehdr->msg_iov,
                           messagehdr->msg_iovlen, &BytesSent,
                           Flags, messagehdr->msg_name,
                           messagehdr->msg_namelen, (LPOVERLAPPED) lpo,
@@ -1415,6 +1469,7 @@ completeio_recv(isc_socket_t *sock, isc_socketevent_t *dev,
                SOFT_OR_HARD(WSAEDISCON, ISC_R_CONNECTIONRESET);
                SOFT_OR_HARD(WSAENETDOWN, ISC_R_NETDOWN);
                ALWAYS_HARD(ERROR_OPERATION_ABORTED, ISC_R_CONNECTIONRESET);
+               ALWAYS_HARD(ERROR_REQUEST_ABORTED, ISC_R_CONNECTIONRESET);
                ALWAYS_HARD(ERROR_NETNAME_DELETED, ISC_R_CONNECTIONRESET);
                ALWAYS_HARD(ERROR_PORT_UNREACHABLE, ISC_R_HOSTUNREACH);
                ALWAYS_HARD(ERROR_HOST_UNREACHABLE, ISC_R_HOSTUNREACH);
@@ -1618,6 +1673,7 @@ completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
                ALWAYS_HARD(ERROR_PORT_UNREACHABLE, ISC_R_HOSTUNREACH);
                ALWAYS_HARD(ERROR_HOST_UNREACHABLE, ISC_R_HOSTUNREACH);
                ALWAYS_HARD(ERROR_NETWORK_UNREACHABLE, ISC_R_NETUNREACH);
+               ALWAYS_HARD(ERROR_REQUEST_ABORTED, ISC_R_CONNECTIONRESET);
                ALWAYS_HARD(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
                ALWAYS_HARD(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH);
                ALWAYS_HARD(WSAEHOSTDOWN, ISC_R_HOSTUNREACH);
@@ -1809,6 +1865,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
        sock->hAlert = NULL;
        sock->evthread_id = 0;
        sock->wait_type = 0;
+       memset(sock->name, 0, sizeof(sock->name));
 
        /*
         * initialize the lock
@@ -2045,10 +2102,7 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
        REQUIRE(VALID_SOCKET(sock));
        REQUIRE(socketp != NULL && *socketp == NULL);
 
-       LOCK(&sock->lock);
-       sock->references++;
-       UNLOCK(&sock->lock);
-
+       InterlockedIncrement(&sock->references);
        *socketp = sock;
 }
 
@@ -2149,6 +2203,8 @@ send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
  * readable event, and the first item on the accept_list should be
  * the done event we want to send.  If the list is empty, this is a no-op,
  * so just unlock and return.
+ *
+ * Note the the socket is locked before entering here
  */
 static void
 internal_accept(isc_socket_t *sock, int accept_errno) {
@@ -2162,7 +2218,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
 
        INSIST(VALID_SOCKET(sock));
 
-       LOCK(&sock->lock);
        socket_log(sock, NULL, TRACE,
                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
                   "internal_accept called, locked socket");
@@ -2197,7 +2252,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
                                         strbuf);
                        break;
                }
-               UNLOCK(&sock->lock);
                return;
        }
 
@@ -2214,7 +2268,34 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
                 */
                addrlen = sizeof(from.type);
                fd = accept(sock->fd, &from.type.sa, &addrlen);
-               if (fd != INVALID_SOCKET) {
+               if (fd == INVALID_SOCKET) {
+                       accept_errno = WSAGetLastError();
+                       if (accept_errno == WSAEMFILE) {
+                               isc_log_iwrite(isc_lctx,
+                                       ISC_LOGCATEGORY_GENERAL,
+                                       ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+                                       isc_msgcat, ISC_MSGSET_SOCKET,
+                                       ISC_MSG_TOOMANYFDS,
+                                       "%s: too many open file descriptors",
+                                       "accept");
+                               goto soft_error;
+                       } else if (SOFT_ERROR(accept_errno) ||
+                                  accept_errno == WSAECONNRESET) {
+                               goto soft_error;
+                       } else {
+                               isc__strerror(accept_errno, strbuf, 
+                                             sizeof(strbuf));
+                               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "internal_accept: accept() %s: %s",
+                                        isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                        strbuf);
+                               fd = INVALID_SOCKET;
+                               result = ISC_R_UNEXPECTED;
+                       }
+               } else {
                        char addrbuf[ISC_SOCKADDR_FORMATSIZE];
                        isc_sockaddr_format(&from, addrbuf, sizeof(addrbuf));
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -2223,7 +2304,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
                                         addrbuf);
                        (void)closesocket(fd);
                }
-               UNLOCK(&sock->lock);
                return;
        }
 
@@ -2296,7 +2376,7 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
        ISC_LIST_UNLINK(sock->accept_list, dev, ev_link);
 
        /*
-        * Stop listing for connects.
+        * Stop listening for connects.
         */
        if (ISC_LIST_EMPTY(sock->accept_list) &&
            WSAEventSelect(sock->fd, sock->hEvent, FD_CLOSE) != 0) {
@@ -2310,7 +2390,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
                                 msg, strbuf);
        }
 
-       UNLOCK(&sock->lock);
 
        if (fd != INVALID_SOCKET) {
                isc_result_t tresult;
@@ -2332,6 +2411,7 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
                dev->newsocket->fd = fd;
                dev->newsocket->bound = 1;
                dev->newsocket->connected = 1;
+               strncpy(sock->name, "acceptconnect", sizeof(sock->name) - 1);
 
                /*
                 * The accept socket inherits the listen socket's
@@ -2377,12 +2457,12 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
        return;
 
  soft_error:
-       UNLOCK(&sock->lock);
        return;
 }
 
 /*
  * Called when a socket with a pending connect() finishes.
+ * Note that the socket is locked before entering.
  */
 static void
 internal_connect(isc_socket_t *sock, int connect_errno) {
@@ -2392,15 +2472,12 @@ internal_connect(isc_socket_t *sock, int connect_errno) {
 
        INSIST(VALID_SOCKET(sock));
 
-       LOCK(&sock->lock);
-
        /*
         * Has this event been canceled?
         */
        dev = sock->connect_ev;
        if (dev == NULL) {
                INSIST(!sock->connecting);
-               UNLOCK(&sock->lock);
                return;
        }
 
@@ -2419,7 +2496,6 @@ internal_connect(isc_socket_t *sock, int connect_errno) {
                    connect_errno == WSAEINPROGRESS)
                {
                        sock->connecting = 1;
-                       UNLOCK(&sock->lock);
                        return;
                }
 
@@ -2452,12 +2528,11 @@ internal_connect(isc_socket_t *sock, int connect_errno) {
                dev->result = ISC_R_SUCCESS;
                sock->connected = 1;
                sock->bound = 1;
+               strncpy(sock->name, "connected", sizeof(sock->name) - 1);
        }
 
        sock->connect_ev = NULL;
 
-       UNLOCK(&sock->lock);
-
        task = dev->ev_sender;
        dev->ev_sender = sock;
        isc_task_sendanddetach(&task, (isc_event_t **)&dev);
@@ -2480,6 +2555,12 @@ internal_recv(isc_socket_t *sock, isc_socketevent_t *dev,
 
        INSIST(sock->pending_recv > 0);
        sock->pending_recv--;
+
+       if (sock->references == 0) {
+               UNLOCK(&sock->lock);
+               destroy_socket(&sock);
+               return;
+       }
        /* If the event is no longer in the list we can just return */
        ldev = ISC_LIST_HEAD(sock->recv_list);
        while (ldev != NULL && ldev != dev) {
@@ -2557,7 +2638,6 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
                break;
        }
 
-
  done:
        UNLOCK(&sock->lock);
 }
@@ -2797,13 +2877,16 @@ event_wait(void *uap) {
                }
 
                if (wsock->references > 0 && wsock->pending_close == 0) {
+                       LOCK(&wsock->lock);
                        if (wsock->listener == 1 &&
                            wsock->pending_accept == 0) {
                                wsock->pending_accept = 1;
                                internal_accept(wsock, event_errno);
-                       }
-                       else {
+                               UNLOCK(&wsock->lock);
+                       else {
                                internal_connect(wsock, event_errno);
+                               UNLOCK(&wsock->lock);
+                               eventlist_event_delete(wsock, evlist, manager);
                        }
                }
        }
@@ -3602,6 +3685,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
        if (cc == 0) {
                sock->connected = 1;
                sock->bound = 1;
+               strncpy(sock->name, "connect", sizeof(sock->name) - 1);
                dev->result = ISC_R_SUCCESS;
                isc_task_send(task, (isc_event_t **)&dev);
 
@@ -3855,7 +3939,6 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
        int onoff = yes ? 1 : 0;
 #else
        UNUSED(yes);
-       UNUSED(sock);
 #endif
 
        REQUIRE(VALID_SOCKET(sock));