diff -up bind-9.3.6-P1/lib/isc/unix/socket.c.rh872587 bind-9.3.6-P1/lib/isc/unix/socket.c --- bind-9.3.6-P1/lib/isc/unix/socket.c.rh872587 2012-11-06 17:55:55.665928160 +0100 +++ bind-9.3.6-P1/lib/isc/unix/socket.c 2012-11-06 18:03:22.668995748 +0100 @@ -2230,16 +2230,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->fd >= 0 && sock->fd < (int)sock->manager->maxsocks); @@ -2252,6 +2250,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; @@ -2259,8 +2259,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); } @@ -2831,6 +2832,7 @@ process_fd(isc_socketmgr_t *manager, int { 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); isc_event_t *sock_selected = NULL; @@ -2847,11 +2849,10 @@ process_fd(isc_socketmgr_t *manager, int } 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; @@ -2867,13 +2868,13 @@ process_fd(isc_socketmgr_t *manager, int 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; @@ -2890,7 +2891,7 @@ check_write: sock); } } - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); + unwatch_write = ISC_TRUE; } if (unlock_sock) UNLOCK(&sock->lock); @@ -2898,6 +2899,13 @@ check_write: if (sock_selected != NULL) { dispatch_selected(manager, sock_selected); } + +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