2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 23:25:38 +00:00

2412. [bug] win32: address a resourse leak. [RT #18374]

This commit is contained in:
Mark Andrews
2008-08-08 05:06:49 +00:00
parent 13caac5ff8
commit dc842cdcb9
8 changed files with 175 additions and 74 deletions

View File

@@ -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 2411. [bug] Allow using a larger number of sockets than FD_SETSIZE
for select(). To enable this, set ISC_SOCKET_MAXSOCKETS for select(). To enable this, set ISC_SOCKET_MAXSOCKETS
at compilation time. [RT #18433] at compilation time. [RT #18433]

View File

@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
@@ -110,7 +110,7 @@ set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
} }
static void static void
init_desc() { init_desc(void) {
int i; int i;
/* Initialize name server statistics */ /* Initialize name server statistics */

View File

@@ -14,10 +14,12 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
#include <config.h>
#include <isc/buffer.h> #include <isc/buffer.h>
#include <isc/httpd.h> #include <isc/httpd.h>
#include <isc/mem.h> #include <isc/mem.h>

View File

@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 #ifndef ISC_HTTPD_H
#define ISC_HTTPD_H 1 #define ISC_HTTPD_H 1
@@ -47,7 +47,7 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdp);
isc_result_t isc_result_t
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url, 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_result_t
isc_httpd_response(isc_httpd_t *httpd); isc_httpd_response(isc_httpd_t *httpd);

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 #ifndef ISC_MSGS_H
#define ISC_MSGS_H 1 #define ISC_MSGS_H 1
@@ -153,7 +153,10 @@
#define ISC_MSG_ACCEPTRETURNED 1418 /*%< accept() returned %d/%s */ #define ISC_MSG_ACCEPTRETURNED 1418 /*%< accept() returned %d/%s */
#define ISC_MSG_TOOMANYFDS 1419 /*%< %s: too many open file descriptors */ #define ISC_MSG_TOOMANYFDS 1419 /*%< %s: too many open file descriptors */
#define ISC_MSG_ZEROPORT 1420 /*%< dropping source port zero packet */ #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_AWAKE 1502 /*%< "awake" */
#define ISC_MSG_WORKING 1503 /*%< "working" */ #define ISC_MSG_WORKING 1503 /*%< "working" */

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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> #include <config.h>
@@ -61,14 +61,24 @@ isc__errno2resultx(int posixerrno, const char *file, int line) {
case EMFILE: case EMFILE:
case WSAEMFILE: case WSAEMFILE:
return (ISC_R_TOOMANYOPENFILES); return (ISC_R_TOOMANYOPENFILES);
case ERROR_OPERATION_ABORTED: case ERROR_CANCELLED:
return (ISC_R_CONNECTIONRESET); return (ISC_R_CANCELED);
case ERROR_PORT_UNREACHABLE: case ERROR_CONNECTION_REFUSED:
return (ISC_R_HOSTUNREACH); return (ISC_R_CONNREFUSED);
case ERROR_CONNECTION_INVALID:
return (ISC_R_NOTCONNECTED);
case ERROR_HOST_UNREACHABLE: case ERROR_HOST_UNREACHABLE:
return (ISC_R_HOSTUNREACH); return (ISC_R_HOSTUNREACH);
case ERROR_NETWORK_UNREACHABLE: case ERROR_NETWORK_UNREACHABLE:
return (ISC_R_NETUNREACH); 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: case WSAEADDRNOTAVAIL:
return (ISC_R_ADDRNOTAVAIL); return (ISC_R_ADDRNOTAVAIL);
case WSAEHOSTUNREACH: case WSAEHOSTUNREACH:

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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> #include <config.h>
@@ -242,7 +242,8 @@ try_ipv6pktinfo(void) {
optname = IPV6_PKTINFO; optname = IPV6_PKTINFO;
#endif #endif
on = 1; 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; ipv6pktinfo_result = ISC_R_NOTFOUND;
goto close; goto close;
} }

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 /* This code has been rewritten to take advantage of Windows Sockets
* I/O Completion Ports and Events. I/O Completion Ports is ONLY * I/O Completion Ports and Events. I/O Completion Ports is ONLY
@@ -129,9 +129,9 @@
#define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0) #define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0)
#define DOIO_SUCCESS 0 /* i/o ok, event sent */ #define DOIO_SUCCESS 0 /* i/o ok, event sent */
#define DOIO_SOFT 1 /* i/o ok, soft error, 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_HARD 2 /* i/o error, event sent */
#define DOIO_EOF 3 /* EOF, no event sent */ #define DOIO_EOF 3 /* EOF, no event sent */
#define DOIO_PENDING 4 /* status when i/o is in process */ #define DOIO_PENDING 4 /* status when i/o is in process */
#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x) #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 */ int msg_totallen; /* total length of this message */
} msghdr; } msghdr;
/*% /*
* The size to raise the recieve buffer to. * The size to raise the receive buffer to.
*/ */
#define RCVBUFSIZE (32*1024) #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) { socket_event_minit(sock_event_list *evlist) {
BOOL bReset; BOOL bReset;
int i; int i;
int stat;
WSAEVENT hEvent;
char strbuf[ISC_STRERRORSIZE];
REQUIRE(evlist != NULL); REQUIRE(evlist != NULL);
/* Initialize the Event List */ /* Initialize the Event List */
@@ -554,9 +557,28 @@ socket_event_minit(sock_event_list *evlist) {
evlist->aEventList[i] = (WSAEVENT) 0; 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)++; (evlist->max_event)++;
bReset = WSAResetEvent(evlist->aEventList[0]); bReset = WSAResetEvent(evlist->aEventList[0]);
return (ISC_R_SUCCESS);
} }
/* /*
* Event Thread Initialization * Event Thread Initialization
@@ -569,7 +591,10 @@ event_thread_create(events_thread_t **evthreadp, isc_socketmgr_t *manager) {
REQUIRE(evthreadp != NULL && *evthreadp == NULL); REQUIRE(evthreadp != NULL && *evthreadp == NULL);
evthread = isc_mem_get(manager->mctx, sizeof(*evthread)); 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); ISC_LINK_INIT(evthread, link);
evthread->manager = manager; evthread->manager = manager;
@@ -645,21 +670,25 @@ socket_eventlist_add(event_change_t *evchange, sock_event_list *evlist,
locate_available_thread(manager); locate_available_thread(manager);
return (ISC_FALSE); return (ISC_FALSE);
} }
/*
* Lock the socket before updating
*/
LOCK(&sock->lock);
evlist->aSockList[max_event] = sock; evlist->aSockList[max_event] = sock;
evlist->aEventList[max_event] = sock->hEvent; evlist->aEventList[max_event] = sock->hEvent;
evlist->max_event++; evlist->max_event++;
evlist->total_events++; evlist->total_events++;
sock->hAlert = evlist->aEventList[0]; sock->hAlert = evlist->aEventList[0];
sock->evthread_id = GetCurrentThreadId(); sock->evthread_id = GetCurrentThreadId();
UNLOCK(&sock->lock);
return (ISC_TRUE); return (ISC_TRUE);
} }
/* /*
* Note that the eventLock is locked before calling this function. * Delete the event from the list
*/ */
isc_boolean_t 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) isc_socketmgr_t *manager)
{ {
int i; int i;
@@ -667,14 +696,11 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
int iEvent = -1; int iEvent = -1;
isc_boolean_t dofree = ISC_FALSE; isc_boolean_t dofree = ISC_FALSE;
REQUIRE(evchange != NULL); REQUIRE(sock != NULL);
/* Make sure this is the right thread from which to delete the event */
if (evchange->evthread_id != GetCurrentThreadId())
return (ISC_FALSE);
REQUIRE(evlist != NULL); REQUIRE(evlist != NULL);
REQUIRE(evchange->hEvent != NULL); REQUIRE(manager != NULL);
hEvent = evchange->hEvent; REQUIRE(sock->hEvent != NULL);
hEvent = sock->hEvent;
/* Find the Event */ /* Find the Event */
for (i = 1; i < evlist->max_event; i++) { 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) if (iEvent < 1)
return (ISC_FALSE); return (ISC_FALSE);
@@ -699,21 +728,25 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
/* Cleanup */ /* Cleanup */
WSACloseEvent(hEvent); WSACloseEvent(hEvent);
LOCK(&evchange->sock->lock); LOCK(&sock->lock);
if (evchange->sock->pending_close) { sock->hEvent = NULL;
evchange->sock->pending_close = 0; sock->hAlert = NULL;
closesocket(evchange->fd); sock->wait_type = 0;
if (sock->pending_close) {
sock->pending_close = 0;
closesocket(sock->fd);
} }
if (evchange->sock->pending_recv == 0 && if (sock->pending_recv == 0 &&
evchange->sock->pending_send == 0 && sock->pending_send == 0 &&
evchange->sock->pending_free) { sock->pending_free) {
evchange->sock->pending_free = 0; sock->pending_free = 0;
ISC_LIST_UNLINK(manager->socklist, evchange->sock, link); ISC_LIST_UNLINK(manager->socklist, sock, link);
dofree = ISC_TRUE; dofree = ISC_TRUE;
} }
UNLOCK(&evchange->sock->lock); UNLOCK(&sock->lock);
if (dofree) if (dofree)
free_socket(&evchange->sock); free_socket(&sock);
if (ISC_LIST_EMPTY(manager->socklist)) if (ISC_LIST_EMPTY(manager->socklist))
SIGNAL(&manager->shutdown_ok); SIGNAL(&manager->shutdown_ok);
@@ -724,6 +757,21 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist,
return (ISC_TRUE); 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 * Get the event changes off of the list and apply the
* requested changes. The manager lock is taken out at * 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) { if (hEvent == WSA_INVALID_EVENT) {
stat = WSAGetLastError(); stat = WSAGetLastError();
isc__strerror(stat, strbuf, sizeof(strbuf)); isc__strerror(stat, strbuf, sizeof(strbuf));
msg = isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, isc_log_iwrite(isc_lctx,
ISC_MSG_FAILED, "failed"), ISC_LOGCATEGORY_GENERAL,
UNEXPECTED_ERROR(__FILE__, __LINE__, "WSACreateEvent: %s: %s", ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
msg, strbuf); isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_TOOMANYHANDLES,
"%s: too many open WSA event handles: %s",
"WSACreateEvent", strbuf);
return (ISC_R_UNEXPECTED); return (ISC_R_UNEXPECTED);
} }
if (WSAEventSelect(sock->fd, hEvent, type) != 0) { 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 void
socket_event_delete(isc_socket_t *sock) { socket_event_delete(isc_socket_t *sock) {
@@ -884,8 +939,6 @@ socket_event_delete(isc_socket_t *sock) {
sock->wait_type = 0; sock->wait_type = 0;
sock->pending_close = 1; sock->pending_close = 1;
notify_eventlist(sock, sock->manager, EVENT_DELETE); notify_eventlist(sock, sock->manager, EVENT_DELETE);
sock->hEvent = NULL;
sock->hAlert = NULL;
sock->evthread_id = 0; sock->evthread_id = 0;
} }
@@ -895,6 +948,7 @@ socket_event_delete(isc_socket_t *sock) {
* with an event, otherwise the WSAWaitForMultipleEvents * with an event, otherwise the WSAWaitForMultipleEvents
* may fail due to the fact that the the Wait should not * may fail due to the fact that the the Wait should not
* be running while closing an event or a socket. * be running while closing an event or a socket.
* The socket is locked before calling this function
*/ */
void void
socket_close(isc_socket_t *sock) { socket_close(isc_socket_t *sock) {
@@ -958,7 +1012,7 @@ internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
int total_sent; int total_sent;
*Error = 0; *Error = 0;
Result = WSASendTo((SOCKET) sock->fd, messagehdr->msg_iov, Result = WSASendTo(sock->fd, messagehdr->msg_iov,
messagehdr->msg_iovlen, &BytesSent, messagehdr->msg_iovlen, &BytesSent,
Flags, messagehdr->msg_name, Flags, messagehdr->msg_name,
messagehdr->msg_namelen, (LPOVERLAPPED) lpo, 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(WSAEDISCON, ISC_R_CONNECTIONRESET);
SOFT_OR_HARD(WSAENETDOWN, ISC_R_NETDOWN); SOFT_OR_HARD(WSAENETDOWN, ISC_R_NETDOWN);
ALWAYS_HARD(ERROR_OPERATION_ABORTED, ISC_R_CONNECTIONRESET); 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_NETNAME_DELETED, ISC_R_CONNECTIONRESET);
ALWAYS_HARD(ERROR_PORT_UNREACHABLE, ISC_R_HOSTUNREACH); ALWAYS_HARD(ERROR_PORT_UNREACHABLE, ISC_R_HOSTUNREACH);
ALWAYS_HARD(ERROR_HOST_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_PORT_UNREACHABLE, ISC_R_HOSTUNREACH);
ALWAYS_HARD(ERROR_HOST_UNREACHABLE, ISC_R_HOSTUNREACH); ALWAYS_HARD(ERROR_HOST_UNREACHABLE, ISC_R_HOSTUNREACH);
ALWAYS_HARD(ERROR_NETWORK_UNREACHABLE, ISC_R_NETUNREACH); ALWAYS_HARD(ERROR_NETWORK_UNREACHABLE, ISC_R_NETUNREACH);
ALWAYS_HARD(ERROR_REQUEST_ABORTED, ISC_R_CONNECTIONRESET);
ALWAYS_HARD(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); ALWAYS_HARD(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
ALWAYS_HARD(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH); ALWAYS_HARD(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH);
ALWAYS_HARD(WSAEHOSTDOWN, 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->hAlert = NULL;
sock->evthread_id = 0; sock->evthread_id = 0;
sock->wait_type = 0; sock->wait_type = 0;
memset(sock->name, 0, sizeof(sock->name));
/* /*
* initialize the lock * initialize the lock
@@ -2045,10 +2102,7 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
REQUIRE(VALID_SOCKET(sock)); REQUIRE(VALID_SOCKET(sock));
REQUIRE(socketp != NULL && *socketp == NULL); REQUIRE(socketp != NULL && *socketp == NULL);
LOCK(&sock->lock); InterlockedIncrement(&sock->references);
sock->references++;
UNLOCK(&sock->lock);
*socketp = sock; *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 * 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, * the done event we want to send. If the list is empty, this is a no-op,
* so just unlock and return. * so just unlock and return.
*
* Note the the socket is locked before entering here
*/ */
static void static void
internal_accept(isc_socket_t *sock, int accept_errno) { 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)); INSIST(VALID_SOCKET(sock));
LOCK(&sock->lock);
socket_log(sock, NULL, TRACE, socket_log(sock, NULL, TRACE,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
"internal_accept called, locked socket"); "internal_accept called, locked socket");
@@ -2197,7 +2252,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
strbuf); strbuf);
break; break;
} }
UNLOCK(&sock->lock);
return; return;
} }
@@ -2214,7 +2268,34 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
*/ */
addrlen = sizeof(from.type); addrlen = sizeof(from.type);
fd = accept(sock->fd, &from.type.sa, &addrlen); 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]; char addrbuf[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_format(&from, addrbuf, sizeof(addrbuf)); isc_sockaddr_format(&from, addrbuf, sizeof(addrbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -2223,7 +2304,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
addrbuf); addrbuf);
(void)closesocket(fd); (void)closesocket(fd);
} }
UNLOCK(&sock->lock);
return; return;
} }
@@ -2296,7 +2376,7 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
ISC_LIST_UNLINK(sock->accept_list, dev, ev_link); ISC_LIST_UNLINK(sock->accept_list, dev, ev_link);
/* /*
* Stop listing for connects. * Stop listening for connects.
*/ */
if (ISC_LIST_EMPTY(sock->accept_list) && if (ISC_LIST_EMPTY(sock->accept_list) &&
WSAEventSelect(sock->fd, sock->hEvent, FD_CLOSE) != 0) { WSAEventSelect(sock->fd, sock->hEvent, FD_CLOSE) != 0) {
@@ -2310,7 +2390,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
msg, strbuf); msg, strbuf);
} }
UNLOCK(&sock->lock);
if (fd != INVALID_SOCKET) { if (fd != INVALID_SOCKET) {
isc_result_t tresult; isc_result_t tresult;
@@ -2332,6 +2411,7 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
dev->newsocket->fd = fd; dev->newsocket->fd = fd;
dev->newsocket->bound = 1; dev->newsocket->bound = 1;
dev->newsocket->connected = 1; dev->newsocket->connected = 1;
strncpy(sock->name, "acceptconnect", sizeof(sock->name) - 1);
/* /*
* The accept socket inherits the listen socket's * The accept socket inherits the listen socket's
@@ -2377,12 +2457,12 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
return; return;
soft_error: soft_error:
UNLOCK(&sock->lock);
return; return;
} }
/* /*
* Called when a socket with a pending connect() finishes. * Called when a socket with a pending connect() finishes.
* Note that the socket is locked before entering.
*/ */
static void static void
internal_connect(isc_socket_t *sock, int connect_errno) { 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)); INSIST(VALID_SOCKET(sock));
LOCK(&sock->lock);
/* /*
* Has this event been canceled? * Has this event been canceled?
*/ */
dev = sock->connect_ev; dev = sock->connect_ev;
if (dev == NULL) { if (dev == NULL) {
INSIST(!sock->connecting); INSIST(!sock->connecting);
UNLOCK(&sock->lock);
return; return;
} }
@@ -2419,7 +2496,6 @@ internal_connect(isc_socket_t *sock, int connect_errno) {
connect_errno == WSAEINPROGRESS) connect_errno == WSAEINPROGRESS)
{ {
sock->connecting = 1; sock->connecting = 1;
UNLOCK(&sock->lock);
return; return;
} }
@@ -2452,12 +2528,11 @@ internal_connect(isc_socket_t *sock, int connect_errno) {
dev->result = ISC_R_SUCCESS; dev->result = ISC_R_SUCCESS;
sock->connected = 1; sock->connected = 1;
sock->bound = 1; sock->bound = 1;
strncpy(sock->name, "connected", sizeof(sock->name) - 1);
} }
sock->connect_ev = NULL; sock->connect_ev = NULL;
UNLOCK(&sock->lock);
task = dev->ev_sender; task = dev->ev_sender;
dev->ev_sender = sock; dev->ev_sender = sock;
isc_task_sendanddetach(&task, (isc_event_t **)&dev); 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); INSIST(sock->pending_recv > 0);
sock->pending_recv--; 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 */ /* If the event is no longer in the list we can just return */
ldev = ISC_LIST_HEAD(sock->recv_list); ldev = ISC_LIST_HEAD(sock->recv_list);
while (ldev != NULL && ldev != dev) { while (ldev != NULL && ldev != dev) {
@@ -2557,7 +2638,6 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
break; break;
} }
done: done:
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
} }
@@ -2797,13 +2877,16 @@ event_wait(void *uap) {
} }
if (wsock->references > 0 && wsock->pending_close == 0) { if (wsock->references > 0 && wsock->pending_close == 0) {
LOCK(&wsock->lock);
if (wsock->listener == 1 && if (wsock->listener == 1 &&
wsock->pending_accept == 0) { wsock->pending_accept == 0) {
wsock->pending_accept = 1; wsock->pending_accept = 1;
internal_accept(wsock, event_errno); internal_accept(wsock, event_errno);
} UNLOCK(&wsock->lock);
else { } else {
internal_connect(wsock, event_errno); 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) { if (cc == 0) {
sock->connected = 1; sock->connected = 1;
sock->bound = 1; sock->bound = 1;
strncpy(sock->name, "connect", sizeof(sock->name) - 1);
dev->result = ISC_R_SUCCESS; dev->result = ISC_R_SUCCESS;
isc_task_send(task, (isc_event_t **)&dev); 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; int onoff = yes ? 1 : 0;
#else #else
UNUSED(yes); UNUSED(yes);
UNUSED(sock);
#endif #endif
REQUIRE(VALID_SOCKET(sock)); REQUIRE(VALID_SOCKET(sock));