diff options
Diffstat (limited to 'lib/isc/unix/socket.c')
-rw-r--r-- | lib/isc/unix/socket.c | 80 |
1 files changed, 56 insertions, 24 deletions
diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 8b006e46b6fa..023f71a86fcf 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.237.18.56.2.1 2008/12/23 00:14:34 marka Exp $ */ +/* $Id: socket.c,v 1.237.18.68 2009/09/07 02:17:09 marka Exp $ */ /*! \file */ @@ -268,7 +268,7 @@ typedef isc_event_t intev_t; #endif /*% - * The size to raise the recieve buffer to (from BIND 8). + * The size to raise the receive buffer to (from BIND 8). */ #define RCVBUFSIZE (32*1024) @@ -1119,7 +1119,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, /* * Construct an iov array and attach it to the msghdr passed in. This is - * the RECV constructor, which will use the avialable region of the buffer + * the RECV constructor, which will use the available region of the buffer * (if using a buffer list) or will use the internal region (if a single * buffer I/O is requested). * @@ -2257,17 +2257,14 @@ isc_socket_detach(isc_socket_t **socketp) { isc_result_t isc_socket_close(isc_socket_t *sock) { int fd; + isc_socketmgr_t *manager; + isc_sockettype_t type; REQUIRE(VALID_SOCKET(sock)); LOCK(&sock->lock); - REQUIRE(sock->references == 1); - UNLOCK(&sock->lock); - /* - * We don't need to retain the lock hereafter, since no one else has - * this socket. - */ + REQUIRE(sock->references == 1); REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks); INSIST(!sock->connecting); @@ -2279,6 +2276,8 @@ isc_socket_close(isc_socket_t *sock) { INSIST(ISC_LIST_EMPTY(sock->accept_list)); INSIST(sock->connect_ev == NULL); + manager = sock->manager; + type = sock->type; fd = sock->fd; sock->fd = -1; sock->listener = 0; @@ -2286,8 +2285,9 @@ isc_socket_close(isc_socket_t *sock) { sock->connecting = 0; sock->bound = 0; isc_sockaddr_any(&sock->address); + UNLOCK(&sock->lock); - closesocket(sock->manager, sock->type, fd); + closesocket(manager, type, fd); return (ISC_R_SUCCESS); } @@ -2517,7 +2517,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { * a documented error for accept(). ECONNABORTED has been * reported for Solaris 8. The rest are thrown in not because * we have seen them but because they are ignored by other - * deamons such as BIND 8 and Apache. + * daemons such as BIND 8 and Apache. */ addrlen = sizeof(dev->newsocket->address.type); @@ -2826,6 +2826,7 @@ process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, { isc_socket_t *sock; isc_boolean_t unlock_sock; + isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE; int lockid = FDLOCK_ID(fd); /* @@ -2841,11 +2842,10 @@ process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, } sock = manager->fds[fd]; - UNLOCK(&manager->fdlock[lockid]); unlock_sock = ISC_FALSE; if (readable) { if (sock == NULL) { - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); + unwatch_read = ISC_TRUE; goto check_write; } unlock_sock = ISC_TRUE; @@ -2856,13 +2856,13 @@ process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, else dispatch_recv(sock); } - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); + unwatch_read = ISC_TRUE; } check_write: if (writeable) { if (sock == NULL) { - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); - return; + unwatch_write = ISC_TRUE; + goto unlock_fd; } if (!unlock_sock) { unlock_sock = ISC_TRUE; @@ -2874,10 +2874,18 @@ check_write: else dispatch_send(sock); } - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); + unwatch_write = ISC_TRUE; } if (unlock_sock) UNLOCK(&sock->lock); + + unlock_fd: + UNLOCK(&manager->fdlock[lockid]); + if (unwatch_read) + (void)unwatch_fd(manager, fd, SELECT_POKE_READ); + if (unwatch_write) + (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); + } #ifdef USE_KQUEUE @@ -3184,7 +3192,7 @@ watcher(void *uap) { #endif } - manager_log(manager, TRACE, + manager_log(manager, TRACE, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_EXITING, "watcher exiting")); @@ -3207,6 +3215,9 @@ isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) { static isc_result_t setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { isc_result_t result; +#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) + char strbuf[ISC_STRERRORSIZE]; +#endif #ifdef USE_KQUEUE manager->nevents = ISC_SOCKET_MAXEVENTS; @@ -3217,6 +3228,12 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { manager->kqueue_fd = kqueue(); if (manager->kqueue_fd == -1) { result = isc__errno2result(errno); + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "kqueue %s: %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed"), + strbuf); isc_mem_put(mctx, manager->events, sizeof(struct kevent) * manager->nevents); return (result); @@ -3240,6 +3257,12 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { manager->epoll_fd = epoll_create(manager->nevents); if (manager->epoll_fd == -1) { result = isc__errno2result(errno); + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "epoll_create %s: %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed"), + strbuf); isc_mem_put(mctx, manager->events, sizeof(struct epoll_event) * manager->nevents); return (result); @@ -3271,13 +3294,19 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { manager->maxsocks); if (manager->fdpollinfo == NULL) { isc_mem_put(mctx, manager->events, - sizeof(pollinfo_t) * manager->maxsocks); + sizeof(struct pollfd) * manager->nevents); return (ISC_R_NOMEMORY); } memset(manager->fdpollinfo, 0, sizeof(pollinfo_t) * manager->maxsocks); manager->devpoll_fd = open("/dev/poll", O_RDWR); if (manager->devpoll_fd == -1) { result = isc__errno2result(errno); + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "open(/dev/poll) %s: %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed"), + strbuf); isc_mem_put(mctx, manager->events, sizeof(struct pollfd) * manager->nevents); isc_mem_put(mctx, manager->fdpollinfo, @@ -3441,7 +3470,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, goto free_manager; } manager->fdstate = isc_mem_get(mctx, manager->maxsocks * sizeof(int)); - if (manager->fds == NULL) { + if (manager->fdstate == NULL) { result = ISC_R_NOMEMORY; goto free_manager; } @@ -3610,7 +3639,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { * Wait for all sockets to be destroyed. */ while (!ISC_LIST_EMPTY(manager->socklist)) { - manager_log(manager, CREATION, + manager_log(manager, CREATION, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SOCKETSREMAIN, "sockets exist")); @@ -3621,7 +3650,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { * Hope all sockets have been destroyed. */ if (!ISC_LIST_EMPTY(manager->socklist)) { - manager_log(manager, CREATION, + manager_log(manager, CREATION, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SOCKETSREMAIN, "sockets exist")); @@ -4453,6 +4482,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_socketmgr_t *manager; int cc; char strbuf[ISC_STRERRORSIZE]; + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; REQUIRE(VALID_SOCKET(sock)); REQUIRE(addr != NULL); @@ -4521,7 +4551,9 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, sock->connected = 0; isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s", errno, strbuf); + isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, "connect(%s) %d/%s", + addrbuf, errno, strbuf); UNLOCK(&sock->lock); isc_event_free(ISC_EVENT_PTR(&dev)); |