From: Yorgos Thessalonikefs Date: Fri, 11 Apr 2025 13:05:52 +0000 (+0200) Subject: Fix WSAPoll (#1265) X-Git-Tag: release-1.23.0rc2~1 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=d6e8ac12890d4f8b18a0b9bbdf90da7f0d3a82c1;p=thirdparty%2Funbound.git 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. --- diff --git a/daemon/remote.c b/daemon/remote.c index 3cf795a69..89134efc9 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3899,6 +3899,7 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event) { int loopcount = 0; /* Loop if the system call returns an errno to do so, like EINTR. */ + log_assert(pollin || pollout); while(1) { struct pollfd p, *fds; int nfds, ret; @@ -3916,11 +3917,11 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event) nfds = 1; memset(&p, 0, sizeof(p)); p.fd = fd; - p.events = POLLERR #ifndef USE_WINSOCK + p.events = POLLERR | POLLHUP -#endif ; +#endif if(pollin) p.events |= POLLIN; if(pollout) @@ -3937,19 +3938,20 @@ sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event) } #endif if(ret == -1) { - if( #ifndef USE_WINSOCK + if( errno == EINTR || errno == EAGAIN # ifdef EWOULDBLOCK || errno == EWOULDBLOCK # endif -#else - WSAGetLastError() == WSAEINTR || - WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEWOULDBLOCK + ) continue; /* Try again. */ #endif - ) - continue; /* Try again. */ + /* For WSAPoll we only get errors here: + * o WSAENETDOWN + * o WSAEFAULT + * o WSAEINVAL + * o WSAENOBUFS + */ log_err("poll: %s", sock_strerror(errno)); if(event) *event = 0; @@ -7398,11 +7400,17 @@ fr_main_handle_cmd(struct fast_reload_thread* fr) # endif #else WSAGetLastError() == WSAEINTR || - WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEWOULDBLOCK + WSAGetLastError() == WSAEINPROGRESS #endif ) 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", sock_strerror(errno)); return; @@ -7434,10 +7442,23 @@ fr_check_cmd_from_thread(struct fast_reload_thread* fr) if(!sock_poll_timeout(fr->commpair[0], 0, 1, 0, &inevent)) { log_err("check for cmd from fast reload thread: " "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; } - 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; + } fr_main_handle_cmd(fr); } } diff --git a/util/netevent.c b/util/netevent.c index f9dff1f9a..0d0fff429 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -456,9 +456,9 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet, int pret; memset(&p, 0, sizeof(p)); p.fd = c->fd; - p.events = POLLOUT | POLLERR + p.events = POLLOUT #ifndef USE_WINSOCK - | POLLHUP + | POLLERR | POLLHUP #endif ; # ifndef USE_WINSOCK @@ -483,7 +483,7 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet, # ifdef EWOULDBLOCK errno != EWOULDBLOCK && # endif - errno != ENOBUFS + errno != ENOMEM && errno != ENOBUFS #else WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEINTR && @@ -496,15 +496,19 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet, return 0; } else if((pret < 0 && #ifndef USE_WINSOCK - errno == ENOBUFS + ( errno == ENOBUFS /* Maybe some systems */ + || errno == ENOMEM /* Linux */ + || errno == EAGAIN) /* Macos, solaris, openbsd */ #else WSAGetLastError() == WSAENOBUFS #endif ) || (send_nobufs && retries > 0)) { - /* ENOBUFS, and poll returned without + /* ENOBUFS/ENOMEM/EAGAIN, and poll + * returned without * a timeout. Or the retried send call - * returned ENOBUFS. It is good to - * wait a bit for the error to clear. */ + * returned ENOBUFS/ENOMEM/EAGAIN. + * It is good to wait a bit for the + * error to clear. */ /* The timeout is 20*(2^(retries+1)), * it increases exponentially, starting * 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)); pret = 0; #endif - if(pret < 0 && + if(pret < 0 #ifndef USE_WINSOCK - errno != EAGAIN && errno != EINTR && + && errno != EAGAIN && errno != EINTR && # ifdef EWOULDBLOCK errno != EWOULDBLOCK && # endif - errno != ENOBUFS + errno != ENOMEM && errno != ENOBUFS #else - WSAGetLastError() != WSAEINPROGRESS && - WSAGetLastError() != WSAEINTR && - WSAGetLastError() != WSAENOBUFS && - WSAGetLastError() != WSAEWOULDBLOCK + /* Sleep does not error */ #endif ) { 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; memset(&p, 0, sizeof(p)); p.fd = c->fd; - p.events = POLLOUT | POLLERR + p.events = POLLOUT #ifndef USE_WINSOCK - | POLLHUP + | POLLERR | POLLHUP #endif ; # ifndef USE_WINSOCK @@ -797,7 +798,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet, # ifdef EWOULDBLOCK errno != EWOULDBLOCK && # endif - errno != ENOBUFS + errno != ENOMEM && errno != ENOBUFS #else WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEINTR && @@ -810,15 +811,19 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet, return 0; } else if((pret < 0 && #ifndef USE_WINSOCK - errno == ENOBUFS + ( errno == ENOBUFS /* Maybe some systems */ + || errno == ENOMEM /* Linux */ + || errno == EAGAIN) /* Macos, solaris, openbsd */ #else WSAGetLastError() == WSAENOBUFS #endif ) || (send_nobufs && retries > 0)) { - /* ENOBUFS, and poll returned without + /* ENOBUFS/ENOMEM/EAGAIN, and poll + * returned without * a timeout. Or the retried send call - * returned ENOBUFS. It is good to - * wait a bit for the error to clear. */ + * returned ENOBUFS/ENOMEM/EAGAIN. + * It is good to wait a bit for the + * error to clear. */ /* The timeout is 20*(2^(retries+1)), * it increases exponentially, starting * 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)); pret = 0; #endif - if(pret < 0 && + if(pret < 0 #ifndef USE_WINSOCK - errno != EAGAIN && errno != EINTR && + && errno != EAGAIN && errno != EINTR && # ifdef EWOULDBLOCK errno != EWOULDBLOCK && # endif - errno != ENOBUFS -#else - WSAGetLastError() != WSAEINPROGRESS && - WSAGetLastError() != WSAEINTR && - WSAGetLastError() != WSAENOBUFS && - WSAGetLastError() != WSAEWOULDBLOCK + errno != ENOMEM && errno != ENOBUFS +#else /* USE_WINSOCK */ + /* Sleep does not error */ #endif ) { log_err("poll udp out timer failed: %s",