2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

Fix select to set and check for exception fds for the connect() function for the socket. Miscellaneous error handling cleanup. [RT #1870]

This commit is contained in:
Danny Mayer
2001-11-07 04:24:38 +00:00
parent be9932698b
commit e209942448

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.c,v 1.6 2001/09/16 06:19:22 mayer Exp $ */
/* $Id: socket.c,v 1.7 2001/11/07 04:24:38 mayer Exp $ */
#define MAKE_EXTERNAL 1
@@ -27,8 +27,6 @@
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
#endif
#include "errno2result.h"
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
@@ -50,10 +48,12 @@
#include <isc/print.h>
#include <isc/region.h>
#include <isc/socket.h>
#include <isc/strerror.h>
#include <isc/task.h>
#include <isc/thread.h>
#include <isc/util.h>
#include "errno2result.h"
/*
* Some systems define the socket length argument as an int, some as size_t,
* some as socklen_t. This is here so it can be easily changed if needed.
@@ -70,9 +70,11 @@
* from recv() but will have errno==0. This is broken, but we have to
* work around it here.
*/
#define SOFT_ERROR(e) ((e) == EAGAIN || \
#define SOFT_ERROR(e) ((e) == WSAEINTR || \
(e) == WSAEWOULDBLOCK || \
(e) == WSAEINTR || \
(e) == EWOULDBLOCK || \
(e) == EINTR || \
(e) == EAGAIN || \
(e) == 0)
#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
@@ -98,8 +100,8 @@
typedef isc_event_t intev_t;
#define SOCKET_MAGIC 0x494f696fU /* IOio */
#define VALID_SOCKET(t) ((t) != NULL && (t)->magic == SOCKET_MAGIC)
#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o')
#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC)
/*
* IPv6 control information. If the socket is an IPv6 socket we want
@@ -156,6 +158,11 @@ struct msghdr {
int msg_flags; /* flags on received message */
} msghdr;
/*
* The number of times a send operation is repeated if the result is EINTR.
*/
#define NRETRIES 10
struct isc_socket {
/* Not locked. */
unsigned int magic;
@@ -197,9 +204,9 @@ struct isc_socket {
#endif
};
#define SOCKET_MANAGER_MAGIC 0x494f6d67U /* IOmg */
#define VALID_MANAGER(m) ((m) != NULL && \
(m)->magic == SOCKET_MANAGER_MAGIC)
#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
struct isc_socketmgr {
/* Not locked. */
unsigned int magic;
@@ -209,6 +216,7 @@ struct isc_socketmgr {
ISC_LIST(isc_socket_t) socklist;
fd_set read_fds;
fd_set write_fds;
fd_set except_fds;
isc_socket_t *fds[FD_SETSIZE];
int fdstate[FD_SETSIZE];
int maxfd;
@@ -256,8 +264,8 @@ static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
#define SELECT_POKE_READ (-3)
#define SELECT_POKE_ACCEPT (-3) /* Same as _READ */
#define SELECT_POKE_WRITE (-4)
#define SELECT_POKE_CONNECT (-4) /* Same as _WRITE */
#define SELECT_POKE_CLOSE (-5)
#define SELECT_POKE_CONNECT (-5)
#define SELECT_POKE_CLOSE (-6)
long bpipe_written = 0;
@@ -315,21 +323,21 @@ internal_sendmsg(int sock, const struct msghdr *msg, int flags) {
NULL,
NULL);
if (Error == SOCKET_ERROR) {
BytesSent = -1;
/* There is an error... */
Error = WSAGetLastError();
if (Error == WSA_IO_PENDING) {
if (Error == SOCKET_ERROR) {
BytesSent = -1;
/* There is an error... */
Error = WSAGetLastError();
if (Error == WSA_IO_PENDING) {
/* Overlapped send successfully initiated. */
errno = EAGAIN;
} else {
/* An unexpected error occurred. */
errno = Error;
}
}
} else {
/* An unexpected error occurred. */
errno = Error;
}
}
/* No error -- the I/O request was completed immediately... */
return (BytesSent);
/* No error -- the I/O request was completed immediately... */
return (BytesSent);
}
int
@@ -394,6 +402,11 @@ manager_log(isc_socketmgr_t *sockmgr,
"sockmgr %p: %s", sockmgr, msgbuf);
}
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, ...) 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,
@@ -432,12 +445,14 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
* process of being closed, start watching it for either reads
* or writes.
*/
INSIST(fd < FD_SETSIZE);
INSIST(fd >= 0 && fd < FD_SETSIZE);
if (manager->fdstate[fd] == CLOSE_PENDING) {
manager->fdstate[fd] = CLOSED;
FD_CLR(fd, &manager->read_fds);
FD_CLR(fd, &manager->write_fds);
FD_CLR(fd, &manager->except_fds);
closesocket(fd);
return;
}
@@ -455,6 +470,10 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
FD_SET(sock->fd, &manager->read_fds);
if (msg == SELECT_POKE_WRITE)
FD_SET(sock->fd, &manager->write_fds);
if (msg == SELECT_POKE_CONNECT) { /* Need both here */
FD_SET(sock->fd, &manager->write_fds);
FD_SET(sock->fd, &manager->except_fds);
}
}
#ifdef ISC_PLATFORM_USETHREADS
@@ -467,7 +486,7 @@ static void
select_poke(isc_socketmgr_t *mgr, int fd, int msg) {
int cc;
int buf[2];
int errval;
char strbuf[ISC_STRERRORSIZE];
buf[0] = fd;
buf[1] = msg;
@@ -475,17 +494,17 @@ select_poke(isc_socketmgr_t *mgr, int fd, int msg) {
if (msg == SELECT_POKE_SHUTDOWN) {
do {
cc = _write(mgr->pipe_fds[1], buf, sizeof(buf));
errval = errno;
} while (cc < 0 && SOFT_ERROR(errno));
if (cc < 0)
if (cc < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
FATAL_ERROR(__FILE__, __LINE__,
isc_msgcat_get(isc_msgcat,
ISC_MSGSET_SOCKET,
isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_WRITEFAILED,
"_write() failed "
"write() failed "
"during watcher poke: %s"),
strerror(errno));
strbuf);
}
INSIST(cc == sizeof(buf));
@@ -502,6 +521,7 @@ static void
select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
int buf[2];
int cc;
char strbuf[ISC_STRERRORSIZE];
cc = _read(mgr->pipe_fds[0], buf, sizeof(buf));
if (cc < 0) {
@@ -509,12 +529,14 @@ select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
if (SOFT_ERROR(errno))
return;
isc__strerror(errno, strbuf, sizeof(strbuf));
FATAL_ERROR(__FILE__, __LINE__,
isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_READFAILED,
"_read() failed "
"read() failed "
"during watcher poke: %s"),
strerror(errno));
strbuf);
return;
}
INSIST(cc == sizeof(buf));
@@ -543,14 +565,16 @@ static isc_result_t
make_nonblock(int fd) {
int ret;
unsigned long flags = 1;
char strbuf[ISC_STRERRORSIZE];
/* Set the socket to non-blocking */
ret = ioctlsocket((SOCKET) fd, FIONBIO, &flags);
if (ret == -1) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"ioctlsocket(%d, FIOBIO, %d): %s",
fd, flags, strerror(errno));
fd, flags, strbuf);
return (ISC_R_UNEXPECTED);
}
@@ -598,12 +622,6 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
dev->attributes |= ISC_SOCKEVENTATTR_CTRUNC;
#endif
/*
* Check for multicast.
*/
if (isc_sockaddr_ismulticast(&dev->address))
dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST;
#ifndef USE_CMSG
return;
#else
@@ -636,6 +654,8 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
ISC_MSG_IFRECEIVED,
"interface received on ifindex %u",
dev->pktinfo.ipi6_ifindex);
if (IN6_IS_ADDR_MULTICAST(&pktinfop->ipi6_addr))
dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST;
goto next;
}
#endif
@@ -752,7 +772,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
msg->msg_control = NULL;
msg->msg_controllen = 0;
msg->msg_flags = 0;
#ifdef USE_CMSG
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6)
if ((sock->type == isc_sockettype_udp)
&& ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) {
struct cmsghdr *cmsgp;
@@ -773,7 +793,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
}
#endif /* USE_CMSG */
#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */
#endif /* ISC_NET_BSD44MSGHDR */
if (write_countp != NULL)
@@ -833,10 +853,8 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
iov[0].buf = (void *)(dev->region.base + dev->n);
iov[0].len = read_count;
iovcount = 1;
}
else {
/*
* Multibuffer I/O.
* Skip empty buffers.
@@ -968,11 +986,13 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
size_t actual_count;
struct msghdr msghdr;
isc_buffer_t *buffer;
int recv_errno;
#if USE_CMSG
char cmsg[CMSG_BUF_SIZE];
#else
char *cmsg = NULL;
#endif
char strbuf[ISC_STRERRORSIZE];
build_msghdr_recv(sock, dev, &msghdr, cmsg, iov, &read_count);
@@ -981,21 +1001,23 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
#endif
cc = internal_recvmsg(sock->fd, &msghdr, 0);
recv_errno = WSAGetLastError();
if (cc < 0) {
if (SOFT_ERROR(errno))
if (SOFT_ERROR(recv_errno))
return (DOIO_SOFT);
if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL))
if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
isc__strerror(recv_errno, strbuf, sizeof(strbuf));
socket_log(sock, NULL, IOEVENT,
isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_DOIORECV,
"doio_recv: internal_recvmsg(%d) %d bytes, "
"err %d/%s",
sock->fd, cc, errno, NTstrerror(errno));
"doio_recv: recvmsg(%d) %d bytes, err %d/%s",
sock->fd, cc, recv_errno, strbuf);
}
#define SOFT_OR_HARD(_system, _isc) \
if (errno == _system) { \
if (recv_errno == _system) { \
if (sock->connected) { \
dev->result = _isc; \
return (DOIO_HARD); \
@@ -1003,7 +1025,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
return (DOIO_SOFT); \
}
#define ALWAYS_HARD(_system, _isc) \
if (errno == _system) { \
if (recv_errno == _system) { \
dev->result = _isc; \
return (DOIO_HARD); \
}
@@ -1020,7 +1042,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
#undef SOFT_OR_HARD
#undef ALWAYS_HARD
dev->result = ISC_R_UNEXPECTED;
dev->result = isc__errno2result(recv_errno);
return (DOIO_HARD);
}
@@ -1120,20 +1142,28 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
#else
char *cmsg = NULL;
#endif
int attempts = 0;
int send_errno;
char strbuf[ISC_STRERRORSIZE];
build_msghdr_send(sock, dev, &msghdr, cmsg, iov, &write_count);
resend:
cc = internal_sendmsg(sock->fd, &msghdr, 0);
send_errno = WSAGetLastError();
/*
* Check for error or block condition.
*/
if (cc < 0) {
if (SOFT_ERROR(errno))
if (send_errno == WSAEINTR && ++attempts < NRETRIES)
goto resend;
if (SOFT_ERROR(send_errno))
return (DOIO_SOFT);
#define SOFT_OR_HARD(_system, _isc) \
if (errno == _system) { \
if (send_errno == _system) { \
if (sock->connected) { \
dev->result = _isc; \
return (DOIO_HARD); \
@@ -1141,7 +1171,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
return (DOIO_SOFT); \
}
#define ALWAYS_HARD(_system, _isc) \
if (errno == _system) { \
if (send_errno == _system) { \
dev->result = _isc; \
return (DOIO_HARD); \
}
@@ -1174,10 +1204,10 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
* a status.
*/
isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"internal_send: %s: %s",
addrbuf, strerror(errno));
dev->result = ISC_R_UNEXPECTED;
isc__strerror(send_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s",
addrbuf, strbuf);
dev->result = isc__errno2result(send_errno);
return (DOIO_HARD);
}
@@ -1220,6 +1250,7 @@ destroy(isc_socket_t **sockp) {
INSIST(ISC_LIST_EMPTY(sock->recv_list));
INSIST(ISC_LIST_EMPTY(sock->send_list));
INSIST(sock->connect_ev == NULL);
REQUIRE(sock->fd >= 0 && sock->fd < FD_SETSIZE);
LOCK(&manager->lock);
@@ -1356,13 +1387,14 @@ free_socket(isc_socket_t **socketp) {
*/
isc_result_t
isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc_socket_t **socketp)
{
isc_socket_t **socketp) {
isc_socket_t *sock = NULL;
isc_result_t ret;
#if defined(USE_CMSG) || defined(SO_BSDCOMPAT)
int on = 1;
#endif
int socket_errno;
char strbuf[ISC_STRERRORSIZE];
REQUIRE(VALID_MANAGER(manager));
REQUIRE(socketp != NULL && *socketp == NULL);
@@ -1380,28 +1412,41 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
break;
}
if (sock->fd >= FD_SETSIZE) {
(void)closesocket(sock->fd);
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", "socket");
free_socket(&sock);
return (ISC_R_NORESOURCES);
}
if (sock->fd < 0) {
socket_errno = WSAGetLastError();
free_socket(&sock);
switch (errno) {
case EMFILE:
case ENFILE:
case ENOBUFS:
switch (socket_errno) {
case WSAEMFILE:
case WSAENOBUFS:
return (ISC_R_NORESOURCES);
case EPROTONOSUPPORT:
case EPFNOSUPPORT:
case EAFNOSUPPORT:
case WSAEPROTONOSUPPORT:
case WSAEPFNOSUPPORT:
case WSAEAFNOSUPPORT:
return (ISC_R_FAMILYNOSUPPORT);
default:
isc__strerror(socket_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"socket() %s: %s",
isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
ISC_MSG_FAILED,
"failed"),
strerror(errno));
strbuf);
return (ISC_R_UNEXPECTED);
}
}
@@ -1414,12 +1459,14 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#ifdef SO_BSDCOMPAT
if (setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT,
(void *)&on, sizeof on) < 0) {
socket_errno = WSAGetLastError();
isc__strerror(socket_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, SO_BSDCOMPAT) %s: %s",
sock->fd,
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"),
strerror(errno));
strbuf);
/* Press on... */
}
#endif
@@ -1430,7 +1477,8 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#if defined(SO_TIMESTAMP)
if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP,
(void *)&on, sizeof on) < 0
&& errno != ENOPROTOOPT) {
&& WSAGetLastError() != WSAENOPROTOOPT) {
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, SO_TIMESTAMP) %s: %s",
sock->fd,
@@ -1438,7 +1486,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
ISC_MSGSET_GENERAL,
ISC_MSG_FAILED,
"failed"),
strerror(errno));
strbuf);
/* Press on... */
}
#endif /* SO_TIMESTAMP */
@@ -1449,6 +1497,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
if ((pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
(void *)&on, sizeof (on)) < 0)) {
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, IPV6_RECVPKTINFO) "
"%s: %s", sock->fd,
@@ -1456,13 +1505,14 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
ISC_MSGSET_GENERAL,
ISC_MSG_FAILED,
"failed"),
strerror(errno));
strbuf);
}
#else
/* 2292 */
if ((pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
(void *)&on, sizeof (on)) < 0)) {
isc__strerror(WSAGetLaastError(), strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, IPV6_PKTINFO) %s: %s",
sock->fd,
@@ -1470,7 +1520,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
ISC_MSGSET_GENERAL,
ISC_MSG_FAILED,
"failed"),
strerror(errno));
strbuf);
}
#endif /* IPV6_RECVPKTINFO */
#ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/
@@ -1730,6 +1780,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
ISC_SOCKADDR_LEN_T addrlen;
int fd;
isc_result_t result = ISC_R_SUCCESS;
int accept_errno;
char strbuf[ISC_STRERRORSIZE];
UNUSED(me);
@@ -1776,16 +1828,18 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
fd = accept(sock->fd, &dev->newsocket->address.type.sa,
(void *)&addrlen);
if (fd < 0) {
if (SOFT_ERROR(errno)) {
accept_errno = WSAGetLastError();
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"),
strerror(errno));
strbuf);
fd = -1;
result = ISC_R_UNEXPECTED;
}
@@ -1810,6 +1864,15 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
sock->pf);
(void)closesocket(fd);
goto soft_error;
} else if (fd >= FD_SETSIZE) {
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");
(void)closesocket(fd);
goto soft_error;
}
}
@@ -1837,13 +1900,13 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
result = ISC_R_UNEXPECTED;
}
LOCK(&manager->lock);
ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);
/*
* -1 means the new socket didn't happen.
*/
if (fd != -1) {
LOCK(&manager->lock);
ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);
dev->newsocket->fd = fd;
dev->newsocket->bound = 1;
dev->newsocket->connected = 1;
@@ -1862,9 +1925,12 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
"accepted connection, new socket %p",
dev->newsocket);
}
UNLOCK(&manager->lock);
} else {
dev->newsocket->references--;
free_socket(&dev->newsocket);
}
/*
* Fill in the done event details and send it off.
@@ -1895,7 +1961,7 @@ internal_recv(isc_task_t *me, isc_event_t *ev) {
LOCK(&sock->lock);
socket_log(sock, NULL, IOEVENT,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
"internal_recv: task %p got event %p", me, ev, sock);
"internal_recv: task %p got event %p", me, ev);
INSIST(sock->pending_recv == 1);
sock->pending_recv = 0;
@@ -1963,7 +2029,7 @@ internal_send(isc_task_t *me, isc_event_t *ev) {
LOCK(&sock->lock);
socket_log(sock, NULL, IOEVENT,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
"internal_send: task %p got event %p", me, ev, sock);
"internal_send: task %p got event %p", me, ev);
INSIST(sock->pending_send == 1);
sock->pending_send = 0;
@@ -2004,11 +2070,14 @@ internal_send(isc_task_t *me, isc_event_t *ev) {
static void
process_fds(isc_socketmgr_t *manager, int maxfd,
fd_set *readfds, fd_set *writefds)
fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
{
int i;
isc_socket_t *sock;
isc_boolean_t unlock_sock;
BOOL conn_check = FALSE;
REQUIRE(maxfd <= FD_SETSIZE);
/*
* Process read/writes on other fds here. Avoid locking
@@ -2019,6 +2088,7 @@ process_fds(isc_socketmgr_t *manager, int maxfd,
manager->fdstate[i] = CLOSED;
FD_CLR(i, &manager->read_fds);
FD_CLR(i, &manager->write_fds);
FD_CLR(i, &manager->except_fds);
closesocket(i);
@@ -2053,13 +2123,37 @@ process_fds(isc_socketmgr_t *manager, int maxfd,
LOCK(&sock->lock);
}
if (!SOCK_DEAD(sock)) {
if (sock->connecting)
if (sock->connecting) {
dispatch_connect(sock);
conn_check = TRUE;
}
else
dispatch_send(sock);
}
FD_CLR(i, &manager->write_fds);
}
if (FD_ISSET(i, exceptfds)) {
if (sock == NULL) {
FD_CLR(i, &manager->except_fds);
continue;
}
if (!unlock_sock) {
unlock_sock = ISC_TRUE;
LOCK(&sock->lock);
}
if (!SOCK_DEAD(sock)) {
if (sock->connecting) {
dispatch_connect(sock);
conn_check = TRUE;
}
}
FD_CLR(i, &manager->write_fds);
FD_CLR(i, &manager->except_fds);
}
// if(sock != NULL && sock->connecting && conn_check == FALSE)
// dispatch_connect(sock);
if (unlock_sock)
UNLOCK(&sock->lock);
}
@@ -2081,8 +2175,10 @@ watcher(void *uap) {
int cc;
fd_set readfds;
fd_set writefds;
fd_set exceptfds;
int msg, fd;
int maxfd;
char strbuf[ISC_STRERRORSIZE];
/* 30 Second timeout on select in case it's necesasary */
struct timeval tv;
@@ -2100,20 +2196,24 @@ watcher(void *uap) {
do {
readfds = manager->read_fds;
writefds = manager->write_fds;
exceptfds = manager->except_fds;
maxfd = manager->maxfd + 1;
UNLOCK(&manager->lock);
cc = select(maxfd, &readfds, &writefds, NULL, &tv);
cc = select(maxfd, &readfds, &writefds, &exceptfds, &tv);
if (cc < 0) {
if (!SOFT_ERROR(errno))
if (!SOFT_ERROR(errno)) {
isc__strerror(errno, strbuf,
sizeof(strbuf));
FATAL_ERROR(__FILE__, __LINE__,
"select() %s: %s",
isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
ISC_MSG_FAILED,
"failed"),
strerror(errno));
strbuf);
}
}
LOCK(&manager->lock);
@@ -2152,7 +2252,7 @@ watcher(void *uap) {
break;
}
}
process_fds(manager, maxfd, &readfds, &writefds);
process_fds(manager, maxfd, &readfds, &writefds, &exceptfds);
}
manager_log(manager, TRACE,
@@ -2170,6 +2270,9 @@ watcher(void *uap) {
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
isc_socketmgr_t *manager;
#ifdef ISC_PLATFORM_USETHREADS
char strbuf[ISC_STRERRORSIZE];
#endif
REQUIRE(managerp != NULL && *managerp == NULL);
@@ -2214,11 +2317,12 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
if (internal_pipe(manager->pipe_fds) != 0) {
DESTROYLOCK(&manager->lock);
isc_mem_put(mctx, manager, sizeof *manager);
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"pipe() %s: %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"),
strerror(errno));
strbuf);
return (ISC_R_UNEXPECTED);
}
@@ -2229,6 +2333,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
*/
FD_ZERO(&manager->read_fds);
FD_ZERO(&manager->write_fds);
FD_ZERO(&manager->except_fds);
manager->maxfd = 0;
memset(manager->fdstate, 0, sizeof(manager->fdstate));
@@ -2565,8 +2670,9 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
case DOIO_SOFT:
/*
* We couldn't send all or part of the request right now, so
* queue it.
* queue it unless ISC_SOCKFLAG_NORETRY is set.
*/
if ((flags & ISC_SOCKFLAG_NORETRY) == 0) {
isc_task_attach(task, &ntask);
dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
@@ -2591,6 +2697,7 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
result = ISC_R_INPROGRESS;
break;
}
case DOIO_HARD:
case DOIO_SUCCESS:
@@ -2698,6 +2805,9 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
isc_socketevent_t *event, unsigned int flags)
{
REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
REQUIRE(sock->type == isc_sockettype_udp);
event->ev_sender = sock;
event->result = ISC_R_UNEXPECTED;
ISC_LIST_INIT(event->bufferlist);
@@ -2711,6 +2821,8 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_result_t
isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) {
int bind_errno;
char strbuf[ISC_STRERRORSIZE];
int on = 1;
LOCK(&sock->lock);
@@ -2730,19 +2842,21 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) {
/* Press on... */
}
if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
bind_errno = WSAGetLastError();
UNLOCK(&sock->lock);
switch (errno) {
case EACCES:
switch (bind_errno) {
case WSAEACCES:
return (ISC_R_NOPERM);
case EADDRNOTAVAIL:
case WSAEADDRNOTAVAIL:
return (ISC_R_ADDRNOTAVAIL);
case EADDRINUSE:
case WSAEADDRINUSE:
return (ISC_R_ADDRINUSE);
case EINVAL:
case WSAEINVAL:
return (ISC_R_BOUND);
default:
UNEXPECTED_ERROR(__FILE__, __LINE__,
"bind: %s", strerror(errno));
isc__strerror(bind_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
strbuf);
return (ISC_R_UNEXPECTED);
}
}
@@ -2767,6 +2881,8 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) {
*/
isc_result_t
isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
char strbuf[ISC_STRERRORSIZE];
REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock);
@@ -2780,8 +2896,9 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
if (listen(sock->fd, (int)backlog) < 0) {
UNLOCK(&sock->lock);
UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s",
strerror(errno));
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf);
return (ISC_R_UNEXPECTED);
}
@@ -2869,6 +2986,8 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
isc_task_t *ntask = NULL;
isc_socketmgr_t *manager;
int cc;
int errval;
char strbuf[ISC_STRERRORSIZE];
REQUIRE(VALID_SOCKET(sock));
REQUIRE(addr != NULL);
@@ -2903,10 +3022,11 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
sock->address = *addr;
cc = connect(sock->fd, &addr->type.sa, addr->length);
if (cc < 0) {
if (SOFT_ERROR(errno) || errno == EINPROGRESS)
errval = WSAGetLastError();
if (SOFT_ERROR(errval) || errval == WSAEINPROGRESS)
goto queue;
switch (errno) {
switch (errval) {
#define ERROR_MATCH(a, b) case a: dev->result = b; goto err_exit;
ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);
ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
@@ -2923,8 +3043,8 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
sock->connected = 0;
UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s",
errno, strerror(errno));
isc__strerror(errval, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s", errval, strbuf);
UNLOCK(&sock->lock);
isc_event_free((isc_event_t **)&dev);
@@ -2986,6 +3106,8 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
isc_task_t *task;
int cc;
ISC_SOCKADDR_LEN_T optlen;
int connect_errno;
char strbuf[ISC_STRERRORSIZE];
UNUSED(me);
INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
@@ -3026,16 +3148,16 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
optlen = sizeof(cc);
if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR,
(void *)&cc, (void *)&optlen) < 0)
cc = errno;
connect_errno = WSAGetLastError();
else
errno = cc;
connect_errno = cc;
if (errno != 0) {
if (connect_errno != 0) {
/*
* If the error is EAGAIN, just re-select on this
* fd and pretend nothing strange happened.
*/
if (SOFT_ERROR(errno) || errno == EINPROGRESS) {
if (SOFT_ERROR(connect_errno) || connect_errno == WSAEINPROGRESS) {
sock->connecting = 1;
select_poke(sock->manager, sock->fd,
SELECT_POKE_CONNECT);
@@ -3047,7 +3169,7 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
/*
* Translate other errors into ISC_R_* flavors.
*/
switch (errno) {
switch (connect_errno) {
#define ERROR_MATCH(a, b) case a: dev->result = b; break;
ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);
ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
@@ -3063,9 +3185,10 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
#undef ERROR_MATCH
default:
dev->result = ISC_R_UNEXPECTED;
isc__strerror(connect_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"internal_connect: connect() %s",
strerror(errno));
strbuf);
}
} else {
dev->result = ISC_R_SUCCESS;
@@ -3107,6 +3230,7 @@ isc_result_t
isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
ISC_SOCKADDR_LEN_T len;
isc_result_t ret;
char strbuf[ISC_STRERRORSIZE];
REQUIRE(VALID_SOCKET(sock));
REQUIRE(addressp != NULL);
@@ -3122,8 +3246,9 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
len = sizeof addressp->type;
if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"getsockname: %s", strerror(errno));
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
strbuf);
ret = ISC_R_UNEXPECTED;
goto out;
}