Skip to content

Commit d6e8ac1

Browse files
committed
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.
1 parent 16ee7cf commit d6e8ac1

File tree

2 files changed

+64
-41
lines changed

2 files changed

+64
-41
lines changed

daemon/remote.c

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3899,6 +3899,7 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
38993899
{
39003900
int loopcount = 0;
39013901
/* Loop if the system call returns an errno to do so, like EINTR. */
3902+
log_assert(pollin || pollout);
39023903
while(1) {
39033904
struct pollfd p, *fds;
39043905
int nfds, ret;
@@ -3916,11 +3917,11 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
39163917
nfds = 1;
39173918
memset(&p, 0, sizeof(p));
39183919
p.fd = fd;
3919-
p.events = POLLERR
39203920
#ifndef USE_WINSOCK
3921+
p.events = POLLERR
39213922
| POLLHUP
3922-
#endif
39233923
;
3924+
#endif
39243925
if(pollin)
39253926
p.events |= POLLIN;
39263927
if(pollout)
@@ -3937,19 +3938,20 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
39373938
}
39383939
#endif
39393940
if(ret == -1) {
3940-
if(
39413941
#ifndef USE_WINSOCK
3942+
if(
39423943
errno == EINTR || errno == EAGAIN
39433944
# ifdef EWOULDBLOCK
39443945
|| errno == EWOULDBLOCK
39453946
# endif
3946-
#else
3947-
WSAGetLastError() == WSAEINTR ||
3948-
WSAGetLastError() == WSAEINPROGRESS ||
3949-
WSAGetLastError() == WSAEWOULDBLOCK
3947+
) continue; /* Try again. */
39503948
#endif
3951-
)
3952-
continue; /* Try again. */
3949+
/* For WSAPoll we only get errors here:
3950+
* o WSAENETDOWN
3951+
* o WSAEFAULT
3952+
* o WSAEINVAL
3953+
* o WSAENOBUFS
3954+
*/
39533955
log_err("poll: %s", sock_strerror(errno));
39543956
if(event)
39553957
*event = 0;
@@ -7398,11 +7400,17 @@ fr_main_handle_cmd(struct fast_reload_thread* fr)
73987400
# endif
73997401
#else
74007402
WSAGetLastError() == WSAEINTR ||
7401-
WSAGetLastError() == WSAEINPROGRESS ||
7402-
WSAGetLastError() == WSAEWOULDBLOCK
7403+
WSAGetLastError() == WSAEINPROGRESS
74037404
#endif
74047405
)
74057406
return; /* Continue later. */
7407+
#ifdef USE_WINSOCK
7408+
if(WSAGetLastError() == WSAEWOULDBLOCK) {
7409+
ub_winsock_tcp_wouldblock(fr->service_event,
7410+
UB_EV_READ);
7411+
return; /* Continue later. */
7412+
}
7413+
#endif
74067414
log_err("read cmd from fast reload thread, recv: %s",
74077415
sock_strerror(errno));
74087416
return;
@@ -7434,10 +7442,23 @@ fr_check_cmd_from_thread(struct fast_reload_thread* fr)
74347442
if(!sock_poll_timeout(fr->commpair[0], 0, 1, 0, &inevent)) {
74357443
log_err("check for cmd from fast reload thread: "
74367444
"poll failed");
7445+
#ifdef USE_WINSOCK
7446+
if(worker->daemon->fast_reload_thread)
7447+
ub_winsock_tcp_wouldblock(worker->daemon->
7448+
fast_reload_thread->service_event,
7449+
UB_EV_READ);
7450+
#endif
74377451
return;
74387452
}
7439-
if(!inevent)
7453+
if(!inevent) {
7454+
#ifdef USE_WINSOCK
7455+
if(worker->daemon->fast_reload_thread)
7456+
ub_winsock_tcp_wouldblock(worker->daemon->
7457+
fast_reload_thread->service_event,
7458+
UB_EV_READ);
7459+
#endif
74407460
return;
7461+
}
74417462
fr_main_handle_cmd(fr);
74427463
}
74437464
}

util/netevent.c

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,9 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
456456
int pret;
457457
memset(&p, 0, sizeof(p));
458458
p.fd = c->fd;
459-
p.events = POLLOUT | POLLERR
459+
p.events = POLLOUT
460460
#ifndef USE_WINSOCK
461-
| POLLHUP
461+
| POLLERR | POLLHUP
462462
#endif
463463
;
464464
# ifndef USE_WINSOCK
@@ -483,7 +483,7 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
483483
# ifdef EWOULDBLOCK
484484
errno != EWOULDBLOCK &&
485485
# endif
486-
errno != ENOBUFS
486+
errno != ENOMEM && errno != ENOBUFS
487487
#else
488488
WSAGetLastError() != WSAEINPROGRESS &&
489489
WSAGetLastError() != WSAEINTR &&
@@ -496,15 +496,19 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
496496
return 0;
497497
} else if((pret < 0 &&
498498
#ifndef USE_WINSOCK
499-
errno == ENOBUFS
499+
( errno == ENOBUFS /* Maybe some systems */
500+
|| errno == ENOMEM /* Linux */
501+
|| errno == EAGAIN) /* Macos, solaris, openbsd */
500502
#else
501503
WSAGetLastError() == WSAENOBUFS
502504
#endif
503505
) || (send_nobufs && retries > 0)) {
504-
/* ENOBUFS, and poll returned without
506+
/* ENOBUFS/ENOMEM/EAGAIN, and poll
507+
* returned without
505508
* a timeout. Or the retried send call
506-
* returned ENOBUFS. It is good to
507-
* wait a bit for the error to clear. */
509+
* returned ENOBUFS/ENOMEM/EAGAIN.
510+
* It is good to wait a bit for the
511+
* error to clear. */
508512
/* The timeout is 20*(2^(retries+1)),
509513
* it increases exponentially, starting
510514
* at 40 msec. After 5 tries, 1240 msec
@@ -517,18 +521,15 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
517521
Sleep((SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
518522
pret = 0;
519523
#endif
520-
if(pret < 0 &&
524+
if(pret < 0
521525
#ifndef USE_WINSOCK
522-
errno != EAGAIN && errno != EINTR &&
526+
&& errno != EAGAIN && errno != EINTR &&
523527
# ifdef EWOULDBLOCK
524528
errno != EWOULDBLOCK &&
525529
# endif
526-
errno != ENOBUFS
530+
errno != ENOMEM && errno != ENOBUFS
527531
#else
528-
WSAGetLastError() != WSAEINPROGRESS &&
529-
WSAGetLastError() != WSAEINTR &&
530-
WSAGetLastError() != WSAENOBUFS &&
531-
WSAGetLastError() != WSAEWOULDBLOCK
532+
/* Sleep does not error */
532533
#endif
533534
) {
534535
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,
770771
int pret;
771772
memset(&p, 0, sizeof(p));
772773
p.fd = c->fd;
773-
p.events = POLLOUT | POLLERR
774+
p.events = POLLOUT
774775
#ifndef USE_WINSOCK
775-
| POLLHUP
776+
| POLLERR | POLLHUP
776777
#endif
777778
;
778779
# ifndef USE_WINSOCK
@@ -797,7 +798,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
797798
# ifdef EWOULDBLOCK
798799
errno != EWOULDBLOCK &&
799800
# endif
800-
errno != ENOBUFS
801+
errno != ENOMEM && errno != ENOBUFS
801802
#else
802803
WSAGetLastError() != WSAEINPROGRESS &&
803804
WSAGetLastError() != WSAEINTR &&
@@ -810,15 +811,19 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
810811
return 0;
811812
} else if((pret < 0 &&
812813
#ifndef USE_WINSOCK
813-
errno == ENOBUFS
814+
( errno == ENOBUFS /* Maybe some systems */
815+
|| errno == ENOMEM /* Linux */
816+
|| errno == EAGAIN) /* Macos, solaris, openbsd */
814817
#else
815818
WSAGetLastError() == WSAENOBUFS
816819
#endif
817820
) || (send_nobufs && retries > 0)) {
818-
/* ENOBUFS, and poll returned without
821+
/* ENOBUFS/ENOMEM/EAGAIN, and poll
822+
* returned without
819823
* a timeout. Or the retried send call
820-
* returned ENOBUFS. It is good to
821-
* wait a bit for the error to clear. */
824+
* returned ENOBUFS/ENOMEM/EAGAIN.
825+
* It is good to wait a bit for the
826+
* error to clear. */
822827
/* The timeout is 20*(2^(retries+1)),
823828
* it increases exponentially, starting
824829
* 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,
831836
Sleep((SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
832837
pret = 0;
833838
#endif
834-
if(pret < 0 &&
839+
if(pret < 0
835840
#ifndef USE_WINSOCK
836-
errno != EAGAIN && errno != EINTR &&
841+
&& errno != EAGAIN && errno != EINTR &&
837842
# ifdef EWOULDBLOCK
838843
errno != EWOULDBLOCK &&
839844
# endif
840-
errno != ENOBUFS
841-
#else
842-
WSAGetLastError() != WSAEINPROGRESS &&
843-
WSAGetLastError() != WSAEINTR &&
844-
WSAGetLastError() != WSAENOBUFS &&
845-
WSAGetLastError() != WSAEWOULDBLOCK
845+
errno != ENOMEM && errno != ENOBUFS
846+
#else /* USE_WINSOCK */
847+
/* Sleep does not error */
846848
#endif
847849
) {
848850
log_err("poll udp out timer failed: %s",

0 commit comments

Comments
 (0)