1627. [bug] win32: sockets were not being closed when the
last external reference was removed. [RT# 11179]
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,3 +1,6 @@
|
||||
1627. [bug] win32: sockets were not being closed when the
|
||||
last external reference was removed. [RT# 11179]
|
||||
|
||||
1626. [bug] --enable-getifaddrs was broken. [RT#11259]
|
||||
|
||||
1625. [placeholder] rt11237
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: config.h.win32,v 1.10 2004/04/19 05:52:21 marka Exp $ */
|
||||
/* $Id: config.h.win32,v 1.11 2004/05/03 23:54:37 marka Exp $ */
|
||||
|
||||
/*
|
||||
* win32 configuration file
|
||||
@@ -104,6 +104,10 @@
|
||||
/* Define if you have h_errno */
|
||||
#define HAVE_H_ERRNO
|
||||
|
||||
#define ISC_PLATFORM_NEEDSTRLCAT
|
||||
|
||||
#define ISC_PLATFORM_NEEDSTRLCPY
|
||||
|
||||
#define S_IFMT _S_IFMT /* file type mask */
|
||||
#define S_IFDIR _S_IFDIR /* directory */
|
||||
#define S_IFCHR _S_IFCHR /* character special */
|
||||
|
||||
@@ -433,6 +433,8 @@ isc_task_getcurrenttime
|
||||
isc_net_probe_ipv6only
|
||||
isc_timermgr_poke
|
||||
isc_net_probe_ipv6pktinfo
|
||||
isc_string_strlcat
|
||||
isc_string_strlcpy
|
||||
|
||||
; Exported Data
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: socket.c,v 1.30 2004/03/05 05:11:59 marka Exp $ */
|
||||
/* $Id: socket.c,v 1.31 2004/05/03 23:54:38 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
|
||||
@@ -239,8 +239,10 @@ struct isc_socket {
|
||||
listener : 1, /* listener socket */
|
||||
connected : 1,
|
||||
connecting : 1, /* connect pending */
|
||||
bound : 1; /* bound to local addr */
|
||||
|
||||
bound : 1, /* bound to local addr */
|
||||
pending_free: 1;
|
||||
unsigned int pending_recv;
|
||||
unsigned int pending_send;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -346,11 +348,8 @@ static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
|
||||
static void free_socket(isc_socket_t **);
|
||||
|
||||
enum {
|
||||
SOCKET_CANCEL,
|
||||
SOCKET_SHUTDOWN,
|
||||
SOCKET_RECV,
|
||||
SOCKET_SEND,
|
||||
SOCK_ACCEPT
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -358,9 +357,6 @@ enum {
|
||||
EVENT_DELETE
|
||||
};
|
||||
|
||||
#define SOCK_DEAD(s) ((s)->references == 0)
|
||||
|
||||
|
||||
#if defined(ISC_SOCKET_DEBUG)
|
||||
/*
|
||||
* This is used to dump the contents of the sock structure
|
||||
@@ -454,7 +450,7 @@ iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) {
|
||||
* We need at least one
|
||||
*/
|
||||
for (i = 0; i < total_threads; i++) {
|
||||
manager->hIOCPThreads[i] = CreateThread( NULL, 0, SocketIoThread,
|
||||
manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread,
|
||||
manager, 0,
|
||||
&manager->dwIOCPThreadIds[i]);
|
||||
if(manager->hIOCPThreads[i] == NULL) {
|
||||
@@ -521,7 +517,8 @@ iocompletionport_exit(isc_socketmgr_t *manager) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Add sockets in here and pass the sock data in as part of the information needed
|
||||
* Add sockets in here and pass the sock data in as part of the
|
||||
* information needed.
|
||||
*/
|
||||
void
|
||||
iocompletionport_update(isc_socket_t *sock) {
|
||||
@@ -652,9 +649,10 @@ socket_eventlist_add(event_change_t *evchange, sock_event_list *evlist,
|
||||
sock->evthread_id = GetCurrentThreadId();
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the eventLock is locked before calling this function
|
||||
* All Events and associated sockes are closed here
|
||||
* 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) {
|
||||
@@ -664,7 +662,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
|
||||
|
||||
REQUIRE(evchange != NULL);
|
||||
/* Make sure this is the right thread from which to delete the event */
|
||||
if(evchange->evthread_id != GetCurrentThreadId())
|
||||
if (evchange->evthread_id != GetCurrentThreadId())
|
||||
return (ISC_FALSE);
|
||||
|
||||
REQUIRE(evlist != NULL);
|
||||
@@ -678,6 +676,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Actual event start at 1 */
|
||||
if (iEvent < 1)
|
||||
return (ISC_FALSE);
|
||||
@@ -686,6 +685,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
|
||||
evlist->aEventList[i] = evlist->aEventList[i + 1];
|
||||
evlist->aSockList[i] = evlist->aSockList[i + 1];
|
||||
}
|
||||
|
||||
evlist->aEventList[evlist->max_event - 1] = 0;
|
||||
evlist->aSockList[evlist->max_event - 1] = NULL;
|
||||
|
||||
@@ -698,6 +698,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) {
|
||||
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the event changes off of the list and apply the
|
||||
* requested changes. The manager lock is taken out at
|
||||
@@ -722,15 +723,20 @@ process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) {
|
||||
|
||||
LOCK(&manager->lock);
|
||||
|
||||
/* First the deletes */
|
||||
/*
|
||||
* First the deletes.
|
||||
*/
|
||||
evchange = ISC_LIST_HEAD(manager->event_updates);
|
||||
while (evchange != NULL) {
|
||||
next = ISC_LIST_NEXT(evchange, link);
|
||||
del = ISC_FALSE;
|
||||
if(evchange->action == EVENT_DELETE) {
|
||||
if (evchange->action == EVENT_DELETE) {
|
||||
del = socket_eventlist_delete(evchange, evlist);
|
||||
|
||||
/* Delete only if this thread's socket list was updated */
|
||||
/*
|
||||
* Delete only if this thread's socket list was
|
||||
* updated.
|
||||
*/
|
||||
if (del) {
|
||||
ISC_LIST_DEQUEUE(manager->event_updates,
|
||||
evchange, link);
|
||||
@@ -740,15 +746,21 @@ process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) {
|
||||
}
|
||||
evchange = next;
|
||||
}
|
||||
/* Now the adds */
|
||||
|
||||
/*
|
||||
* Now the adds.
|
||||
*/
|
||||
evchange = ISC_LIST_HEAD(manager->event_updates);
|
||||
while (evchange != NULL) {
|
||||
next = ISC_LIST_NEXT(evchange, link);
|
||||
del = ISC_FALSE;
|
||||
if(evchange->action == EVENT_ADD) {
|
||||
if (evchange->action == EVENT_ADD) {
|
||||
del = socket_eventlist_add(evchange, evlist, manager);
|
||||
|
||||
/* Delete only if this thread's socket list was updated */
|
||||
/*
|
||||
* Delete only if this thread's socket list was
|
||||
* updated.
|
||||
*/
|
||||
if (del) {
|
||||
ISC_LIST_DEQUEUE(manager->event_updates,
|
||||
evchange, link);
|
||||
@@ -761,13 +773,15 @@ process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) {
|
||||
UNLOCK(&manager->lock);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the event list changes to the queue and notify the
|
||||
* event loop
|
||||
*/
|
||||
static void
|
||||
notify_eventlist(isc_socket_t *sock, isc_socketmgr_t *manager,
|
||||
unsigned int action) {
|
||||
unsigned int action)
|
||||
{
|
||||
|
||||
event_change_t *evchange;
|
||||
|
||||
@@ -793,6 +807,7 @@ notify_eventlist(isc_socket_t *sock, isc_socketmgr_t *manager,
|
||||
else
|
||||
WSASetEvent(manager->prime_alert);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the socket is already locked before calling this function
|
||||
*/
|
||||
@@ -830,6 +845,7 @@ socket_event_add(isc_socket_t *sock, long type) {
|
||||
notify_eventlist(sock, sock->manager, EVENT_ADD);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the socket is not locked before calling this function
|
||||
*/
|
||||
@@ -847,8 +863,8 @@ socket_event_delete(isc_socket_t *sock) {
|
||||
sock->hAlert = NULL;
|
||||
sock->evthread_id = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine to cleanup and then close the socket.
|
||||
* Only close the socket here if it is NOT associated
|
||||
@@ -872,6 +888,7 @@ socket_close(isc_socket_t *sock) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize socket services
|
||||
*/
|
||||
@@ -893,7 +910,8 @@ BOOL InitSockets() {
|
||||
|
||||
int
|
||||
internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
|
||||
struct msghdr *messagehdr, int flags, int *Error) {
|
||||
struct msghdr *messagehdr, int flags, int *Error)
|
||||
{
|
||||
int Result;
|
||||
DWORD BytesSent;
|
||||
DWORD Flags = flags;
|
||||
@@ -918,19 +936,20 @@ internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
|
||||
*Error = WSAGetLastError();
|
||||
|
||||
switch (*Error) {
|
||||
case WSA_IO_INCOMPLETE :
|
||||
case WSA_WAIT_IO_COMPLETION :
|
||||
case WSA_IO_PENDING :
|
||||
sock->pending_send++;
|
||||
case NO_ERROR :
|
||||
break;
|
||||
|
||||
case NO_ERROR :
|
||||
case WSA_IO_INCOMPLETE :
|
||||
case WSA_WAIT_IO_COMPLETION :
|
||||
case WSA_IO_PENDING :
|
||||
break;
|
||||
|
||||
default :
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(lpo != NULL)
|
||||
default :
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
sock->pending_send++;
|
||||
if (lpo != NULL)
|
||||
return (0);
|
||||
else
|
||||
return (total_sent);
|
||||
@@ -938,7 +957,8 @@ internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
|
||||
|
||||
int
|
||||
internal_recvmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
|
||||
struct msghdr *messagehdr, int flags, int *Error) {
|
||||
struct msghdr *messagehdr, int flags, int *Error)
|
||||
{
|
||||
DWORD Flags = 0;
|
||||
DWORD NumBytes = 0;
|
||||
int total_bytes = 0;
|
||||
@@ -946,14 +966,14 @@ internal_recvmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
|
||||
|
||||
*Error = 0;
|
||||
Result = WSARecvFrom((SOCKET) sock->fd,
|
||||
messagehdr->msg_iov,
|
||||
messagehdr->msg_iovlen,
|
||||
&NumBytes,
|
||||
&Flags,
|
||||
messagehdr->msg_name,
|
||||
(int *)&(messagehdr->msg_namelen),
|
||||
(LPOVERLAPPED) lpo,
|
||||
NULL);
|
||||
messagehdr->msg_iov,
|
||||
messagehdr->msg_iovlen,
|
||||
&NumBytes,
|
||||
&Flags,
|
||||
messagehdr->msg_name,
|
||||
(int *)&(messagehdr->msg_namelen),
|
||||
(LPOVERLAPPED) lpo,
|
||||
NULL);
|
||||
|
||||
total_bytes = (int) NumBytes;
|
||||
|
||||
@@ -963,31 +983,32 @@ internal_recvmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
|
||||
*Error = WSAGetLastError();
|
||||
|
||||
switch (*Error) {
|
||||
case WSA_IO_INCOMPLETE:
|
||||
case WSA_WAIT_IO_COMPLETION:
|
||||
case WSA_IO_PENDING:
|
||||
sock->pending_recv++;
|
||||
case NO_ERROR:
|
||||
break;
|
||||
|
||||
case NO_ERROR :
|
||||
case WSA_IO_INCOMPLETE :
|
||||
case WSA_WAIT_IO_COMPLETION :
|
||||
case WSA_IO_PENDING :
|
||||
break;
|
||||
default :
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
sock->pending_recv++;
|
||||
|
||||
default :
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Return the flags received in header */
|
||||
messagehdr->msg_flags = Flags;
|
||||
if(lpo != NULL)
|
||||
if (lpo != NULL)
|
||||
return (-1);
|
||||
else
|
||||
return (total_bytes);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
manager_log(isc_socketmgr_t *sockmgr,
|
||||
isc_logcategory_t *category, isc_logmodule_t *module, int level,
|
||||
const char *fmt, ...) {
|
||||
manager_log(isc_socketmgr_t *sockmgr, isc_logcategory_t *category,
|
||||
isc_logmodule_t *module, int level, const char *fmt, ...)
|
||||
{
|
||||
char msgbuf[2048];
|
||||
va_list ap;
|
||||
|
||||
@@ -1007,11 +1028,13 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
|
||||
isc_logcategory_t *category, isc_logmodule_t *module, int level,
|
||||
isc_msgcat_t *msgcat, int msgset, int message,
|
||||
const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10);
|
||||
|
||||
static void
|
||||
socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
|
||||
isc_logcategory_t *category, isc_logmodule_t *module, int level,
|
||||
isc_msgcat_t *msgcat, int msgset, int message,
|
||||
const char *fmt, ...) {
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char msgbuf[2048];
|
||||
char peerbuf[256];
|
||||
va_list ap;
|
||||
@@ -1058,6 +1081,7 @@ make_nonblock(SOCKET fd) {
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
|
||||
* to not work correctly, returning a WSACONNRESET error when a WSASendTo
|
||||
@@ -1107,7 +1131,8 @@ connection_reset_fix(SOCKET fd) {
|
||||
static void
|
||||
build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
struct msghdr *msg, char *cmsg,
|
||||
WSABUF *iov, size_t *write_countp) {
|
||||
WSABUF *iov, size_t *write_countp)
|
||||
{
|
||||
unsigned int iovcount;
|
||||
isc_buffer_t *buffer;
|
||||
isc_region_t used;
|
||||
@@ -1194,7 +1219,8 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
static void
|
||||
build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
struct msghdr *msg, char *cmsg,
|
||||
WSABUF *iov, size_t *read_countp) {
|
||||
WSABUF *iov, size_t *read_countp)
|
||||
{
|
||||
unsigned int iovcount;
|
||||
isc_buffer_t *buffer;
|
||||
isc_region_t available;
|
||||
@@ -1224,10 +1250,10 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
iov[0].len = read_count;
|
||||
iovcount = 1;
|
||||
} else {
|
||||
/*
|
||||
* Multibuffer I/O.
|
||||
* Skip empty buffers.
|
||||
*/
|
||||
/*
|
||||
* Multibuffer I/O.
|
||||
* Skip empty buffers.
|
||||
*/
|
||||
while (buffer != NULL) {
|
||||
REQUIRE(ISC_BUFFER_VALID(buffer));
|
||||
if (isc_buffer_availablelength(buffer) != 0)
|
||||
@@ -1266,7 +1292,8 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
|
||||
static void
|
||||
set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
|
||||
isc_socketevent_t *dev) {
|
||||
isc_socketevent_t *dev)
|
||||
{
|
||||
if (sock->type == isc_sockettype_udp) {
|
||||
if (address != NULL)
|
||||
dev->address = *address;
|
||||
@@ -1280,14 +1307,14 @@ set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
|
||||
|
||||
static isc_socketevent_t *
|
||||
allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
|
||||
isc_taskaction_t action, const void *arg) {
|
||||
isc_taskaction_t action, const void *arg)
|
||||
{
|
||||
isc_socketevent_t *ev;
|
||||
|
||||
ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
|
||||
sock, eventtype,
|
||||
action, arg,
|
||||
sizeof(*ev));
|
||||
|
||||
if (ev == NULL)
|
||||
return (NULL);
|
||||
|
||||
@@ -1324,7 +1351,8 @@ dump_msg(struct msghdr *msg, isc_socket_t *sock) {
|
||||
|
||||
static int
|
||||
completeio_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
struct msghdr *messagehdr, int cc, int recv_errno) {
|
||||
struct msghdr *messagehdr, int cc, int recv_errno)
|
||||
{
|
||||
size_t actual_count;
|
||||
isc_buffer_t *buffer;
|
||||
|
||||
@@ -1442,31 +1470,27 @@ completeio_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
dev->result = ISC_R_SUCCESS;
|
||||
return (DOIO_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
startio_recv(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
|
||||
BOOL bwait, int *recv_errno) {
|
||||
int *recv_errno)
|
||||
{
|
||||
char *cmsg = NULL;
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
IoCompletionInfo *lpo;
|
||||
int status;
|
||||
struct msghdr messagehdr;
|
||||
struct msghdr *msghdr;
|
||||
|
||||
if (!bwait) {
|
||||
lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle,
|
||||
HEAP_ZERO_MEMORY, sizeof(IoCompletionInfo));
|
||||
lpo->request_type = SOCKET_RECV;
|
||||
lpo->dev = dev;
|
||||
msghdr = &lpo->messagehdr;
|
||||
} else { /* Wait for recv to complete */
|
||||
lpo = NULL;
|
||||
msghdr = &messagehdr;
|
||||
}
|
||||
sock->references++;
|
||||
lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle,
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(IoCompletionInfo));
|
||||
lpo->request_type = SOCKET_RECV;
|
||||
lpo->dev = dev;
|
||||
msghdr = &lpo->messagehdr;
|
||||
memset(msghdr, 0, sizeof(struct msghdr));
|
||||
|
||||
build_msghdr_recv(sock, dev, msghdr, cmsg, sock->iov,
|
||||
&(sock->totalBytes));
|
||||
&(sock->totalBytes));
|
||||
|
||||
#if defined(ISC_SOCKET_DEBUG)
|
||||
dump_msg(msghdr, sock);
|
||||
@@ -1485,13 +1509,12 @@ startio_recv(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
|
||||
socket_log(sock, NULL, IOEVENT,
|
||||
isc_msgcat, ISC_MSGSET_SOCKET,
|
||||
ISC_MSG_DOIORECV,
|
||||
"startio_recv: recvmsg(%d) %d bytes, err %d/%s",
|
||||
"startio_recv: recvmsg(%d) %d bytes, "
|
||||
"err %d/%s",
|
||||
sock->fd, *nbytes, *recv_errno, strbuf);
|
||||
}
|
||||
status = completeio_recv(sock, dev, msghdr, *nbytes, *recv_errno);
|
||||
if(status != DOIO_SOFT) {
|
||||
sock->references--;
|
||||
}
|
||||
status = completeio_recv(sock, dev, msghdr,
|
||||
*nbytes, *recv_errno);
|
||||
goto done;
|
||||
}
|
||||
dev->result = ISC_R_SUCCESS;
|
||||
@@ -1499,6 +1522,7 @@ startio_recv(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
|
||||
done:
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns:
|
||||
* DOIO_SUCCESS The operation succeeded. dev->result contains
|
||||
@@ -1513,8 +1537,9 @@ done:
|
||||
* No other return values are possible.
|
||||
*/
|
||||
static int
|
||||
completeio_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messagehdr, int cc,
|
||||
int send_errno) {
|
||||
completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
struct msghdr *messagehdr, int cc, int send_errno)
|
||||
{
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
|
||||
@@ -1592,28 +1617,24 @@ completeio_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messa
|
||||
dev->result = ISC_R_SUCCESS;
|
||||
return (DOIO_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
|
||||
BOOL bwait, int *send_errno) {
|
||||
int *send_errno)
|
||||
{
|
||||
char *cmsg = NULL;
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
IoCompletionInfo *lpo;
|
||||
int status;
|
||||
struct msghdr messagehdr;
|
||||
struct msghdr *msghdr;
|
||||
|
||||
if (!bwait) {
|
||||
lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle,
|
||||
HEAP_ZERO_MEMORY, sizeof(IoCompletionInfo));
|
||||
lpo->request_type = SOCKET_SEND;
|
||||
lpo->dev = dev;
|
||||
msghdr = &lpo->messagehdr;
|
||||
} else { /* Wait for send to complete */
|
||||
lpo = NULL;
|
||||
msghdr = &messagehdr;
|
||||
}
|
||||
lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle,
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(IoCompletionInfo));
|
||||
lpo->request_type = SOCKET_SEND;
|
||||
lpo->dev = dev;
|
||||
msghdr = &lpo->messagehdr;
|
||||
memset(msghdr, 0, sizeof(struct msghdr));
|
||||
sock->references++;
|
||||
|
||||
build_msghdr_send(sock, dev, msghdr, cmsg, sock->iov,
|
||||
&(sock->totalBytes));
|
||||
@@ -1631,13 +1652,12 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
|
||||
socket_log(sock, NULL, IOEVENT,
|
||||
isc_msgcat, ISC_MSGSET_SOCKET,
|
||||
ISC_MSG_INTERNALSEND,
|
||||
"startio_send: internal_sendmsg(%d) %d bytes, err %d/%s",
|
||||
"startio_send: internal_sendmsg(%d) %d "
|
||||
"bytes, err %d/%s",
|
||||
sock->fd, *nbytes, *send_errno, strbuf);
|
||||
}
|
||||
status = completeio_send(sock, dev, msghdr, *nbytes, *send_errno);
|
||||
if(status != DOIO_SOFT) {
|
||||
sock->references--;
|
||||
}
|
||||
status = completeio_send(sock, dev, msghdr,
|
||||
*nbytes, *send_errno);
|
||||
goto done;
|
||||
}
|
||||
dev->result = ISC_R_SUCCESS;
|
||||
@@ -1645,6 +1665,7 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
|
||||
done:
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Kill.
|
||||
*
|
||||
@@ -1655,6 +1676,7 @@ static void
|
||||
destroy_socket(isc_socket_t **sockp) {
|
||||
isc_socket_t *sock = *sockp;
|
||||
isc_socketmgr_t *manager = sock->manager;
|
||||
isc_boolean_t dofree = ISC_TRUE;
|
||||
|
||||
REQUIRE(sock != NULL);
|
||||
|
||||
@@ -1668,15 +1690,14 @@ destroy_socket(isc_socket_t **sockp) {
|
||||
|
||||
LOCK(&manager->lock);
|
||||
|
||||
/*
|
||||
* No one has this socket open and the socket doesn't have to be
|
||||
* locked. The socket_close function makes sure that if needed
|
||||
* the event_wait loop removes any associated event from the list
|
||||
* of events being waited on.
|
||||
*/
|
||||
LOCK(&sock->lock);
|
||||
socket_close(sock);
|
||||
|
||||
if (sock->pending_recv != 0 || sock->pending_send != 0) {
|
||||
dofree = ISC_FALSE;
|
||||
sock->pending_free = 1;
|
||||
}
|
||||
ISC_LIST_UNLINK(manager->socklist, sock, link);
|
||||
UNLOCK(&sock->lock);
|
||||
|
||||
if (ISC_LIST_EMPTY(manager->socklist))
|
||||
SIGNAL(&manager->shutdown_ok);
|
||||
@@ -1684,10 +1705,10 @@ destroy_socket(isc_socket_t **sockp) {
|
||||
/*
|
||||
* XXX should reset manager->maxfd here
|
||||
*/
|
||||
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
free_socket(sockp);
|
||||
if (dofree)
|
||||
free_socket(sockp);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@@ -1721,6 +1742,9 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
|
||||
sock->connect_ev = NULL;
|
||||
sock->pending_accept = 0;
|
||||
sock->pending_close = 0;
|
||||
sock->pending_recv = 0;
|
||||
sock->pending_send = 0;
|
||||
sock->pending_free = 0;
|
||||
sock->iocp = 0;
|
||||
sock->listener = 0;
|
||||
sock->connected = 0;
|
||||
@@ -2066,14 +2090,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) {
|
||||
INSIST(sock->pending_accept == 1);
|
||||
sock->pending_accept = 0;
|
||||
|
||||
INSIST(sock->references > 0);
|
||||
sock->references--; /* the internal event is done with this socket */
|
||||
if (sock->references == 0) {
|
||||
UNLOCK(&sock->lock);
|
||||
destroy_socket(&sock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check any possible error status from the event notification here.
|
||||
* Note that we don't take any action since it was only
|
||||
@@ -2284,18 +2300,6 @@ internal_connect(isc_socket_t *sock, int connect_errno) {
|
||||
|
||||
LOCK(&sock->lock);
|
||||
|
||||
/*
|
||||
* When the internal event was sent the reference count was bumped
|
||||
* to keep the socket around for us. Decrement the count here.
|
||||
*/
|
||||
INSIST(sock->references > 0);
|
||||
sock->references--;
|
||||
if (sock->references == 0) {
|
||||
UNLOCK(&sock->lock);
|
||||
destroy_socket(&sock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Has this event been canceled?
|
||||
*/
|
||||
@@ -2366,7 +2370,9 @@ internal_connect(isc_socket_t *sock, int connect_errno) {
|
||||
}
|
||||
|
||||
static void
|
||||
internal_recv(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messagehdr, int nbytes, int recv_errno) {
|
||||
internal_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
struct msghdr *messagehdr, int nbytes, int recv_errno)
|
||||
{
|
||||
isc_socketevent_t *ldev;
|
||||
int io_state;
|
||||
int cc;
|
||||
@@ -2378,14 +2384,8 @@ internal_recv(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message
|
||||
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
|
||||
"internal_recv: task got socket event %p", dev);
|
||||
|
||||
INSIST(sock->references > 0);
|
||||
sock->references--; /* the internal event is done with this socket */
|
||||
if (sock->references == 0) {
|
||||
UNLOCK(&sock->lock);
|
||||
destroy_socket(&sock);
|
||||
return;
|
||||
}
|
||||
|
||||
INSIST(sock->pending_recv > 0);
|
||||
sock->pending_recv--;
|
||||
/* 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) {
|
||||
@@ -2398,34 +2398,36 @@ internal_recv(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message
|
||||
* Try to do as much I/O as possible on this socket. There are no
|
||||
* limits here, currently.
|
||||
*/
|
||||
switch (completeio_recv(sock, dev, messagehdr, nbytes, recv_errno)) {
|
||||
case DOIO_SOFT:
|
||||
cc = 0;
|
||||
recv_errno = 0;
|
||||
io_state = startio_recv(sock, dev, &cc, FALSE, &recv_errno);
|
||||
goto done;
|
||||
switch (completeio_recv(sock, dev, messagehdr, nbytes, recv_errno)) {
|
||||
case DOIO_SOFT:
|
||||
cc = 0;
|
||||
recv_errno = 0;
|
||||
io_state = startio_recv(sock, dev, &cc, &recv_errno);
|
||||
goto done;
|
||||
|
||||
case DOIO_EOF:
|
||||
/*
|
||||
* read of 0 means the remote end was closed.
|
||||
* Run through the event queue and dispatch all
|
||||
* the events with an EOF result code.
|
||||
*/
|
||||
dev->result = ISC_R_EOF;
|
||||
send_recvdone_event(sock, &dev);
|
||||
goto done;
|
||||
case DOIO_EOF:
|
||||
/*
|
||||
* read of 0 means the remote end was closed.
|
||||
* Run through the event queue and dispatch all
|
||||
* the events with an EOF result code.
|
||||
*/
|
||||
dev->result = ISC_R_EOF;
|
||||
send_recvdone_event(sock, &dev);
|
||||
goto done;
|
||||
|
||||
case DOIO_SUCCESS:
|
||||
case DOIO_HARD:
|
||||
send_recvdone_event(sock, &dev);
|
||||
break;
|
||||
}
|
||||
case DOIO_SUCCESS:
|
||||
case DOIO_HARD:
|
||||
send_recvdone_event(sock, &dev);
|
||||
break;
|
||||
}
|
||||
done:
|
||||
UNLOCK(&sock->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
internal_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messagehdr, int nbytes, int send_errno) {
|
||||
internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||
struct msghdr *messagehdr, int nbytes, int send_errno)
|
||||
{
|
||||
isc_socketevent_t *ldev;
|
||||
int io_state;
|
||||
int cc;
|
||||
@@ -2440,13 +2442,8 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message
|
||||
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
|
||||
"internal_send: task got socket event %p", dev);
|
||||
|
||||
INSIST(sock->references > 0);
|
||||
sock->references--; /* the internal event is done with this socket */
|
||||
if (sock->references == 0) {
|
||||
UNLOCK(&sock->lock);
|
||||
destroy_socket(&sock);
|
||||
return;
|
||||
}
|
||||
INSIST(sock->pending_send > 0);
|
||||
sock->pending_send--;
|
||||
|
||||
/* If the event is no longer in the list we can just return */
|
||||
ldev = ISC_LIST_HEAD(sock->send_list);
|
||||
@@ -2463,7 +2460,7 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message
|
||||
case DOIO_SOFT:
|
||||
cc = 0;
|
||||
send_errno = 0;
|
||||
io_state = startio_send(sock, dev, &cc, FALSE, &send_errno);
|
||||
io_state = startio_send(sock, dev, &cc, &send_errno);
|
||||
goto done;
|
||||
|
||||
case DOIO_HARD:
|
||||
@@ -2487,8 +2484,6 @@ SocketIoThread(LPVOID ThreadContext) {
|
||||
isc_socketmgr_t *manager = ThreadContext;
|
||||
BOOL bSuccess = FALSE;
|
||||
DWORD nbytes;
|
||||
DWORD tbytes;
|
||||
DWORD tflags;
|
||||
IoCompletionInfo *lpo = NULL;
|
||||
isc_socket_t *sock = NULL;
|
||||
int request;
|
||||
@@ -2504,7 +2499,9 @@ SocketIoThread(LPVOID ThreadContext) {
|
||||
* preempt normal recv packet processing, but not
|
||||
* higher than the timer sync thread.
|
||||
*/
|
||||
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL)) {
|
||||
if (!SetThreadPriority(GetCurrentThread(),
|
||||
THREAD_PRIORITY_ABOVE_NORMAL))
|
||||
{
|
||||
errval = GetLastError();
|
||||
isc__strerror(errval, strbuf, sizeof(strbuf));
|
||||
FATAL_ERROR(__FILE__, __LINE__,
|
||||
@@ -2514,33 +2511,53 @@ SocketIoThread(LPVOID ThreadContext) {
|
||||
strbuf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Loop forever waiting on I/O Completions and then processing them
|
||||
*/
|
||||
while(TRUE) {
|
||||
while (TRUE) {
|
||||
bSuccess = GetQueuedCompletionStatus (
|
||||
manager->hIoCompletionPort,
|
||||
&nbytes,
|
||||
(LPDWORD) &sock,
|
||||
(LPOVERLAPPED *)&lpo,
|
||||
INFINITE
|
||||
);
|
||||
if(lpo == NULL ) {
|
||||
INFINITE);
|
||||
if (lpo == NULL) {
|
||||
/*
|
||||
* Received request to exit
|
||||
*/
|
||||
break;
|
||||
}
|
||||
errstatus = 0;
|
||||
if(!bSuccess) {
|
||||
if (!bSuccess) {
|
||||
isc_boolean_t dofree = ISC_FALSE;
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
/*
|
||||
* I/O Failure
|
||||
* Find out why
|
||||
* Was this the socket closed under us?
|
||||
*/
|
||||
WSAGetOverlappedResult(sock->fd, (LPWSAOVERLAPPED) &lpo,
|
||||
&tbytes, FALSE, &tflags);
|
||||
dev = lpo->dev;
|
||||
errstatus = WSAGetLastError();
|
||||
if (nbytes == 0 && errstatus == WSA_OPERATION_ABORTED) {
|
||||
LOCK(&sock->lock);
|
||||
switch (lpo->request_type) {
|
||||
case SOCKET_RECV:
|
||||
INSIST(sock->pending_recv > 0);
|
||||
sock->pending_recv--;
|
||||
break;
|
||||
case SOCKET_SEND:
|
||||
INSIST(sock->pending_send > 0);
|
||||
sock->pending_send--;
|
||||
break;
|
||||
}
|
||||
if (sock->pending_recv == 0 &&
|
||||
sock->pending_send == 0 &&
|
||||
sock->pending_free)
|
||||
dofree = ISC_TRUE;
|
||||
UNLOCK(&sock->lock);
|
||||
if (dofree)
|
||||
free_socket(&sock);
|
||||
if (lpo != NULL)
|
||||
HeapFree(hHeapHandle, 0, lpo);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
request = lpo->request_type;
|
||||
@@ -2548,20 +2565,17 @@ SocketIoThread(LPVOID ThreadContext) {
|
||||
messagehdr = &lpo->messagehdr;
|
||||
|
||||
switch (request) {
|
||||
case SOCKET_CANCEL:
|
||||
break;
|
||||
case SOCKET_RECV:
|
||||
internal_recv(sock, dev, messagehdr, nbytes, errstatus);
|
||||
break;
|
||||
case SOCKET_SEND:
|
||||
internal_send(sock, dev, messagehdr, nbytes, errstatus);
|
||||
break;
|
||||
default:
|
||||
break; /* Unknown: Just ignore it */
|
||||
}
|
||||
if (lpo != NULL)
|
||||
HeapFree(hHeapHandle, 0, lpo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit Completion Port Thread
|
||||
*/
|
||||
@@ -2570,6 +2584,7 @@ SocketIoThread(LPVOID ThreadContext) {
|
||||
ISC_MSG_EXITING, "SocketIoThread exiting"));
|
||||
return ((isc_threadresult_t)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the thread that will loop forever, waiting for an event to
|
||||
* happen.
|
||||
@@ -2631,7 +2646,6 @@ event_wait(void *uap) {
|
||||
} while (cc < 0 && !manager->bShutdown
|
||||
&& manager->event_written == 0);
|
||||
|
||||
|
||||
if (manager->bShutdown)
|
||||
break;
|
||||
|
||||
@@ -2690,11 +2704,9 @@ event_wait(void *uap) {
|
||||
if (wsock->listener == 1 &&
|
||||
wsock->pending_accept == 0) {
|
||||
wsock->pending_accept = 1;
|
||||
wsock->references++;
|
||||
internal_accept(wsock, event_errno);
|
||||
}
|
||||
else {
|
||||
wsock->references++;
|
||||
internal_connect(wsock, event_errno);
|
||||
}
|
||||
}
|
||||
@@ -2706,6 +2718,7 @@ event_wait(void *uap) {
|
||||
|
||||
return ((isc_threadresult_t)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new socket manager.
|
||||
*/
|
||||
@@ -2861,7 +2874,8 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
|
||||
|
||||
static isc_result_t
|
||||
socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
|
||||
unsigned int flags) {
|
||||
unsigned int flags)
|
||||
{
|
||||
int io_state;
|
||||
int cc = 0;
|
||||
isc_task_t *ntask = NULL;
|
||||
@@ -2872,7 +2886,7 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
|
||||
|
||||
LOCK(&sock->lock);
|
||||
iocompletionport_update(sock);
|
||||
io_state = startio_recv(sock, dev, &cc, FALSE, &recv_errno);
|
||||
io_state = startio_recv(sock, dev, &cc, &recv_errno);
|
||||
|
||||
switch (io_state) {
|
||||
case DOIO_SOFT:
|
||||
@@ -3050,7 +3064,7 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
|
||||
LOCK(&sock->lock);
|
||||
have_lock = ISC_TRUE;
|
||||
iocompletionport_update(sock);
|
||||
io_state = startio_send(sock, dev, &cc, FALSE, &send_errno);
|
||||
io_state = startio_send(sock, dev, &cc, &send_errno);
|
||||
|
||||
switch (io_state) {
|
||||
case DOIO_SOFT:
|
||||
@@ -3642,8 +3656,8 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
|
||||
isc_socket_newconnev_t *next;
|
||||
isc_task_t *current_task;
|
||||
|
||||
dev = ISC_LIST_HEAD(sock->accept_list);
|
||||
socket_event_delete(sock);
|
||||
dev = ISC_LIST_HEAD(sock->accept_list);
|
||||
|
||||
while (dev != NULL) {
|
||||
current_task = dev->ev_sender;
|
||||
|
||||
Reference in New Issue
Block a user