diff --git a/CHANGES b/CHANGES index 642aec1c5d..21c2ac5780 100644 --- a/CHANGES +++ b/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 diff --git a/config.h.win32 b/config.h.win32 index 486fa4c832..ab3f7a9f06 100644 --- a/config.h.win32 +++ b/config.h.win32 @@ -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 */ diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def index 85074d4bc1..e0c7cd2c16 100644 --- a/lib/isc/win32/libisc.def +++ b/lib/isc/win32/libisc.def @@ -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 diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index 377b8e1a09..e94cecd818 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -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;