mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Fix WSAPoll (#1265)
* Fix calling WSAPoll. * fast_reload: explicitly set tcp_wouldblock on Windows when there is no command to read from the fast_reload thread. * For poll(), also check for ENOMEM (Linux). * Remove ifdefs for ENOMEM. * Some systems return EAGAIN for poll.
This commit is contained in:
parent
4f06e658d1
commit
75e8fd7539
2 changed files with 64 additions and 41 deletions
|
|
@ -3899,6 +3899,7 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
|
||||||
{
|
{
|
||||||
int loopcount = 0;
|
int loopcount = 0;
|
||||||
/* Loop if the system call returns an errno to do so, like EINTR. */
|
/* Loop if the system call returns an errno to do so, like EINTR. */
|
||||||
|
log_assert(pollin || pollout);
|
||||||
while(1) {
|
while(1) {
|
||||||
struct pollfd p, *fds;
|
struct pollfd p, *fds;
|
||||||
int nfds, ret;
|
int nfds, ret;
|
||||||
|
|
@ -3916,11 +3917,11 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
|
||||||
nfds = 1;
|
nfds = 1;
|
||||||
memset(&p, 0, sizeof(p));
|
memset(&p, 0, sizeof(p));
|
||||||
p.fd = fd;
|
p.fd = fd;
|
||||||
p.events = POLLERR
|
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
|
p.events = POLLERR
|
||||||
| POLLHUP
|
| POLLHUP
|
||||||
#endif
|
|
||||||
;
|
;
|
||||||
|
#endif
|
||||||
if(pollin)
|
if(pollin)
|
||||||
p.events |= POLLIN;
|
p.events |= POLLIN;
|
||||||
if(pollout)
|
if(pollout)
|
||||||
|
|
@ -3937,19 +3938,20 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(ret == -1) {
|
if(ret == -1) {
|
||||||
if(
|
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
|
if(
|
||||||
errno == EINTR || errno == EAGAIN
|
errno == EINTR || errno == EAGAIN
|
||||||
# ifdef EWOULDBLOCK
|
# ifdef EWOULDBLOCK
|
||||||
|| errno == EWOULDBLOCK
|
|| errno == EWOULDBLOCK
|
||||||
# endif
|
# endif
|
||||||
#else
|
) continue; /* Try again. */
|
||||||
WSAGetLastError() == WSAEINTR ||
|
|
||||||
WSAGetLastError() == WSAEINPROGRESS ||
|
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK
|
|
||||||
#endif
|
#endif
|
||||||
)
|
/* For WSAPoll we only get errors here:
|
||||||
continue; /* Try again. */
|
* o WSAENETDOWN
|
||||||
|
* o WSAEFAULT
|
||||||
|
* o WSAEINVAL
|
||||||
|
* o WSAENOBUFS
|
||||||
|
*/
|
||||||
log_err("poll: %s", sock_strerror(errno));
|
log_err("poll: %s", sock_strerror(errno));
|
||||||
if(event)
|
if(event)
|
||||||
*event = 0;
|
*event = 0;
|
||||||
|
|
@ -7392,11 +7394,17 @@ fr_main_handle_cmd(struct fast_reload_thread* fr)
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
WSAGetLastError() == WSAEINTR ||
|
WSAGetLastError() == WSAEINTR ||
|
||||||
WSAGetLastError() == WSAEINPROGRESS ||
|
WSAGetLastError() == WSAEINPROGRESS
|
||||||
WSAGetLastError() == WSAEWOULDBLOCK
|
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
return; /* Continue later. */
|
return; /* Continue later. */
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
if(WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||||
|
ub_winsock_tcp_wouldblock(fr->service_event,
|
||||||
|
UB_EV_READ);
|
||||||
|
return; /* Continue later. */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
log_err("read cmd from fast reload thread, recv: %s",
|
log_err("read cmd from fast reload thread, recv: %s",
|
||||||
sock_strerror(errno));
|
sock_strerror(errno));
|
||||||
return;
|
return;
|
||||||
|
|
@ -7428,10 +7436,23 @@ fr_check_cmd_from_thread(struct fast_reload_thread* fr)
|
||||||
if(!sock_poll_timeout(fr->commpair[0], 0, 1, 0, &inevent)) {
|
if(!sock_poll_timeout(fr->commpair[0], 0, 1, 0, &inevent)) {
|
||||||
log_err("check for cmd from fast reload thread: "
|
log_err("check for cmd from fast reload thread: "
|
||||||
"poll failed");
|
"poll failed");
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
if(worker->daemon->fast_reload_thread)
|
||||||
|
ub_winsock_tcp_wouldblock(worker->daemon->
|
||||||
|
fast_reload_thread->service_event,
|
||||||
|
UB_EV_READ);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!inevent)
|
if(!inevent) {
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
if(worker->daemon->fast_reload_thread)
|
||||||
|
ub_winsock_tcp_wouldblock(worker->daemon->
|
||||||
|
fast_reload_thread->service_event,
|
||||||
|
UB_EV_READ);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
fr_main_handle_cmd(fr);
|
fr_main_handle_cmd(fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -456,9 +456,9 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||||
int pret;
|
int pret;
|
||||||
memset(&p, 0, sizeof(p));
|
memset(&p, 0, sizeof(p));
|
||||||
p.fd = c->fd;
|
p.fd = c->fd;
|
||||||
p.events = POLLOUT | POLLERR
|
p.events = POLLOUT
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
| POLLHUP
|
| POLLERR | POLLHUP
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
# ifndef USE_WINSOCK
|
# ifndef USE_WINSOCK
|
||||||
|
|
@ -483,7 +483,7 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||||
# ifdef EWOULDBLOCK
|
# ifdef EWOULDBLOCK
|
||||||
errno != EWOULDBLOCK &&
|
errno != EWOULDBLOCK &&
|
||||||
# endif
|
# endif
|
||||||
errno != ENOBUFS
|
errno != ENOMEM && errno != ENOBUFS
|
||||||
#else
|
#else
|
||||||
WSAGetLastError() != WSAEINPROGRESS &&
|
WSAGetLastError() != WSAEINPROGRESS &&
|
||||||
WSAGetLastError() != WSAEINTR &&
|
WSAGetLastError() != WSAEINTR &&
|
||||||
|
|
@ -496,15 +496,19 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||||
return 0;
|
return 0;
|
||||||
} else if((pret < 0 &&
|
} else if((pret < 0 &&
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
errno == ENOBUFS
|
( errno == ENOBUFS /* Maybe some systems */
|
||||||
|
|| errno == ENOMEM /* Linux */
|
||||||
|
|| errno == EAGAIN) /* Macos, solaris, openbsd */
|
||||||
#else
|
#else
|
||||||
WSAGetLastError() == WSAENOBUFS
|
WSAGetLastError() == WSAENOBUFS
|
||||||
#endif
|
#endif
|
||||||
) || (send_nobufs && retries > 0)) {
|
) || (send_nobufs && retries > 0)) {
|
||||||
/* ENOBUFS, and poll returned without
|
/* ENOBUFS/ENOMEM/EAGAIN, and poll
|
||||||
|
* returned without
|
||||||
* a timeout. Or the retried send call
|
* a timeout. Or the retried send call
|
||||||
* returned ENOBUFS. It is good to
|
* returned ENOBUFS/ENOMEM/EAGAIN.
|
||||||
* wait a bit for the error to clear. */
|
* It is good to wait a bit for the
|
||||||
|
* error to clear. */
|
||||||
/* The timeout is 20*(2^(retries+1)),
|
/* The timeout is 20*(2^(retries+1)),
|
||||||
* it increases exponentially, starting
|
* it increases exponentially, starting
|
||||||
* at 40 msec. After 5 tries, 1240 msec
|
* at 40 msec. After 5 tries, 1240 msec
|
||||||
|
|
@ -517,18 +521,15 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||||
Sleep((SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
Sleep((SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
||||||
pret = 0;
|
pret = 0;
|
||||||
#endif
|
#endif
|
||||||
if(pret < 0 &&
|
if(pret < 0
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
errno != EAGAIN && errno != EINTR &&
|
&& errno != EAGAIN && errno != EINTR &&
|
||||||
# ifdef EWOULDBLOCK
|
# ifdef EWOULDBLOCK
|
||||||
errno != EWOULDBLOCK &&
|
errno != EWOULDBLOCK &&
|
||||||
# endif
|
# endif
|
||||||
errno != ENOBUFS
|
errno != ENOMEM && errno != ENOBUFS
|
||||||
#else
|
#else
|
||||||
WSAGetLastError() != WSAEINPROGRESS &&
|
/* Sleep does not error */
|
||||||
WSAGetLastError() != WSAEINTR &&
|
|
||||||
WSAGetLastError() != WSAENOBUFS &&
|
|
||||||
WSAGetLastError() != WSAEWOULDBLOCK
|
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
log_err("poll udp out timer failed: %s",
|
log_err("poll udp out timer failed: %s",
|
||||||
|
|
@ -770,9 +771,9 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
|
||||||
int pret;
|
int pret;
|
||||||
memset(&p, 0, sizeof(p));
|
memset(&p, 0, sizeof(p));
|
||||||
p.fd = c->fd;
|
p.fd = c->fd;
|
||||||
p.events = POLLOUT | POLLERR
|
p.events = POLLOUT
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
| POLLHUP
|
| POLLERR | POLLHUP
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
# ifndef USE_WINSOCK
|
# ifndef USE_WINSOCK
|
||||||
|
|
@ -797,7 +798,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
|
||||||
# ifdef EWOULDBLOCK
|
# ifdef EWOULDBLOCK
|
||||||
errno != EWOULDBLOCK &&
|
errno != EWOULDBLOCK &&
|
||||||
# endif
|
# endif
|
||||||
errno != ENOBUFS
|
errno != ENOMEM && errno != ENOBUFS
|
||||||
#else
|
#else
|
||||||
WSAGetLastError() != WSAEINPROGRESS &&
|
WSAGetLastError() != WSAEINPROGRESS &&
|
||||||
WSAGetLastError() != WSAEINTR &&
|
WSAGetLastError() != WSAEINTR &&
|
||||||
|
|
@ -810,15 +811,19 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
|
||||||
return 0;
|
return 0;
|
||||||
} else if((pret < 0 &&
|
} else if((pret < 0 &&
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
errno == ENOBUFS
|
( errno == ENOBUFS /* Maybe some systems */
|
||||||
|
|| errno == ENOMEM /* Linux */
|
||||||
|
|| errno == EAGAIN) /* Macos, solaris, openbsd */
|
||||||
#else
|
#else
|
||||||
WSAGetLastError() == WSAENOBUFS
|
WSAGetLastError() == WSAENOBUFS
|
||||||
#endif
|
#endif
|
||||||
) || (send_nobufs && retries > 0)) {
|
) || (send_nobufs && retries > 0)) {
|
||||||
/* ENOBUFS, and poll returned without
|
/* ENOBUFS/ENOMEM/EAGAIN, and poll
|
||||||
|
* returned without
|
||||||
* a timeout. Or the retried send call
|
* a timeout. Or the retried send call
|
||||||
* returned ENOBUFS. It is good to
|
* returned ENOBUFS/ENOMEM/EAGAIN.
|
||||||
* wait a bit for the error to clear. */
|
* It is good to wait a bit for the
|
||||||
|
* error to clear. */
|
||||||
/* The timeout is 20*(2^(retries+1)),
|
/* The timeout is 20*(2^(retries+1)),
|
||||||
* it increases exponentially, starting
|
* it increases exponentially, starting
|
||||||
* at 40 msec. After 5 tries, 1240 msec
|
* at 40 msec. After 5 tries, 1240 msec
|
||||||
|
|
@ -831,18 +836,15 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
|
||||||
Sleep((SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
Sleep((SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
|
||||||
pret = 0;
|
pret = 0;
|
||||||
#endif
|
#endif
|
||||||
if(pret < 0 &&
|
if(pret < 0
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
errno != EAGAIN && errno != EINTR &&
|
&& errno != EAGAIN && errno != EINTR &&
|
||||||
# ifdef EWOULDBLOCK
|
# ifdef EWOULDBLOCK
|
||||||
errno != EWOULDBLOCK &&
|
errno != EWOULDBLOCK &&
|
||||||
# endif
|
# endif
|
||||||
errno != ENOBUFS
|
errno != ENOMEM && errno != ENOBUFS
|
||||||
#else
|
#else /* USE_WINSOCK */
|
||||||
WSAGetLastError() != WSAEINPROGRESS &&
|
/* Sleep does not error */
|
||||||
WSAGetLastError() != WSAEINTR &&
|
|
||||||
WSAGetLastError() != WSAENOBUFS &&
|
|
||||||
WSAGetLastError() != WSAEWOULDBLOCK
|
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
log_err("poll udp out timer failed: %s",
|
log_err("poll udp out timer failed: %s",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue