fi
# Checks for header files.
-for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h
+for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
fi
-for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex
+for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex poll
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
fi
# Checks for header files.
-AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h],,, [AC_INCLUDES_DEFAULT])
# net/if.h portability for Darwin see:
# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Header-Portability.html
AC_CHECK_HEADERS([net/if.h],,, [
AC_MSG_RESULT(no))
AC_SEARCH_LIBS([setusercontext], [util])
-AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex])
+AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex poll])
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#define NUM_UDP_PER_SELECT 1
#endif
+/** timeout in millisec to wait for write to unblock, packets dropped after.*/
+#define SEND_BLOCKED_WAIT_TIMEOUT 200
+
/**
* The internal event structure for keeping ub_event info for the event.
* Possibly other structures (list, tree) this is part of.
* we want to send the answer, and we will wait for
* the ethernet interface buffer to have space. */
#ifndef USE_WINSOCK
- if(errno == EAGAIN ||
+ if(errno == EAGAIN || errno == EINTR ||
# ifdef EWOULDBLOCK
errno == EWOULDBLOCK ||
# endif
errno == ENOBUFS) {
#else
if(WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAENOBUFS ||
WSAGetLastError() == WSAEWOULDBLOCK) {
#endif
* have a blocking fd that they operate on */
while(
#ifndef USE_WINSOCK
- errno == EAGAIN ||
+ errno == EAGAIN || errno == EINTR ||
# ifdef EWOULDBLOCK
errno == EWOULDBLOCK ||
# endif
errno == ENOBUFS
#else
WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAENOBUFS ||
WSAGetLastError() == WSAEWOULDBLOCK
#endif
) {
+#if defined(HAVE_POLL) || defined(USE_WINSOCK)
+ struct pollfd p;
+ int pret;
+ memset(&p, 0, sizeof(p));
+ p.fd = c->fd;
+ p.events = POLLOUT | POLLERR | POLLHUP;
+# ifndef USE_WINSOCK
+ pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT);
+# else
+ pret = WSAPoll(&p, 1,
+ SEND_BLOCKED_WAIT_TIMEOUT);
+# endif
+ if(pret == 0) {
+ /* timer expired */
+ verbose(VERB_OPS, "send udp blocked "
+ "for long, dropping packet.");
+ return 0;
+ } else if(pret < 0 &&
+#ifndef USE_WINSOCK
+ errno != EAGAIN && errno != EINTR &&
+# ifdef EWOULDBLOCK
+ errno != EWOULDBLOCK &&
+# endif
+ errno != ENOBUFS
+#else
+ WSAGetLastError() != WSAEINPROGRESS &&
+ WSAGetLastError() != WSAEINTR &&
+ WSAGetLastError() != WSAENOBUFS &&
+ WSAGetLastError() != WSAEWOULDBLOCK
+#endif
+ ) {
+ log_err("poll udp out failed: %s",
+ sock_strerror(errno));
+ return 0;
+ }
+#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */
if (!is_connected) {
sent = sendto(c->fd, (void*)sldns_buffer_begin(packet),
sldns_buffer_remaining(packet), 0,
* we want to send the answer, and we will wait for
* the ethernet interface buffer to have space. */
#ifndef USE_WINSOCK
- if(errno == EAGAIN ||
+ if(errno == EAGAIN || errno == EINTR ||
# ifdef EWOULDBLOCK
errno == EWOULDBLOCK ||
# endif
errno == ENOBUFS) {
#else
if(WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAENOBUFS ||
WSAGetLastError() == WSAEWOULDBLOCK) {
#endif
while(
#ifndef USE_WINSOCK
- errno == EAGAIN ||
+ errno == EAGAIN || errno == EINTR ||
# ifdef EWOULDBLOCK
errno == EWOULDBLOCK ||
# endif
errno == ENOBUFS
#else
WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAENOBUFS ||
WSAGetLastError() == WSAEWOULDBLOCK
#endif
) {
+#if defined(HAVE_POLL) || defined(USE_WINSOCK)
+ struct pollfd p;
+ int pret;
+ memset(&p, 0, sizeof(p));
+ p.fd = c->fd;
+ p.events = POLLOUT | POLLERR | POLLHUP;
+# ifndef USE_WINSOCK
+ pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT);
+# else
+ pret = WSAPoll(&p, 1,
+ SEND_BLOCKED_WAIT_TIMEOUT);
+# endif
+ if(pret == 0) {
+ /* timer expired */
+ verbose(VERB_OPS, "send udp blocked "
+ "for long, dropping packet.");
+ return 0;
+ } else if(pret < 0 &&
+#ifndef USE_WINSOCK
+ errno != EAGAIN && errno != EINTR &&
+# ifdef EWOULDBLOCK
+ errno != EWOULDBLOCK &&
+# endif
+ errno != ENOBUFS
+#else
+ WSAGetLastError() != WSAEINPROGRESS &&
+ WSAGetLastError() != WSAEINTR &&
+ WSAGetLastError() != WSAENOBUFS &&
+ WSAGetLastError() != WSAEWOULDBLOCK
+#endif
+ ) {
+ log_err("poll udp out failed: %s",
+ sock_strerror(errno));
+ return 0;
+ }
+#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */
sent = sendmsg(c->fd, &msg, 0);
}
}