]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
detect nonblocking broken.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 7 Nov 2008 14:28:06 +0000 (14:28 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 7 Nov 2008 14:28:06 +0000 (14:28 +0000)
git-svn-id: file:///svn/unbound/trunk@1338 be551aaa-1e26-0410-a405-d3ace91eadb9

config.h.in
configure
configure.ac
doc/Changelog
util/netevent.c

index 308718c0059b450cdf931a8e99e7cff624383fba..973856ac0e6e08800fb1022d3b7849fa3e20c2e6 100644 (file)
 /* Define if mkdir has one argument. */
 #undef MKDIR_HAS_ONE_ARG
 
+/* Define if the network stack does not fully support nonblocking io (causes
+   lower performance). */
+#undef NONBLOCKING_IS_BROKEN
+
 /* Define to the address where bug reports for this package should be sent. */
 #undef PACKAGE_BUGREPORT
 
index 5dcea7ea9e75275fb50355a18fa9c983ef4bf12e..69c5cffad5ca3f58affe5b349fb799fb56602d4c 100755 (executable)
--- a/configure
+++ b/configure
@@ -25012,6 +25012,192 @@ _ACEOF
 
 fi
 
+# check if select and nonblocking sockets actually work.
+{ echo "$as_me:$LINENO: checking if nonblocking sockets work" >&5
+echo $ECHO_N "checking if nonblocking sockets work... $ECHO_C" >&6; }
+if test "$cross_compiling" = yes; then
+
+       { echo "$as_me:$LINENO: result: crosscompile(yes)" >&5
+echo "${ECHO_T}crosscompile(yes)" >&6; }
+
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+int
+main ()
+{
+
+       int port;
+       int sfd, cfd;
+       int num = 10;
+       int i, p;
+       struct sockaddr_in a;
+       /* test if select and nonblocking reads work well together */
+       /* open port.
+          fork child to send 10 messages.
+          select to read.
+          then try to nonblocking read the 10 messages
+          then, nonblocking read must give EAGAIN
+       */
+
+       port = 12345 + (time(0)%32);
+       sfd = socket(PF_INET, SOCK_DGRAM, 0);
+       if(sfd == -1) {
+               perror("socket");
+               return 1;
+       }
+       memset(&a, 0, sizeof(a));
+       a.sin_family = AF_INET;
+       a.sin_port = htons(port);
+       a.sin_addr.s_addr = inet_addr("127.0.0.1");
+       if(bind(sfd, (struct sockaddr*)&a, sizeof(a)) < 0) {
+               perror("bind");
+               return 1;
+       }
+       if(fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) {
+               perror("fcntl");
+               return 1;
+       }
+
+       cfd = socket(PF_INET, SOCK_DGRAM, 0);
+       if(cfd == -1) {
+               perror("client socket");
+               return 1;
+       }
+       a.sin_port = 0;
+       if(bind(cfd, (struct sockaddr*)&a, sizeof(a)) < 0) {
+               perror("client bind");
+               return 1;
+       }
+       a.sin_port = htons(port);
+
+       /* no handler, causes exit in 10 seconds */
+       alarm(10);
+
+       /* send and receive on the socket */
+       if((p=fork()) == 0) {
+               for(i=0; i<num; i++) {
+                       if(sendto(cfd, &i, sizeof(i), 0,
+                               (struct sockaddr*)&a, sizeof(a)) < 0) {
+                               perror("sendto");
+                               return 1;
+                       }
+               }
+       } else {
+               /* parent */
+               fd_set rset;
+               int x;
+               if(p == -1) {
+                       perror("fork");
+                       return 1;
+               }
+               FD_ZERO(&rset);
+               FD_SET(sfd, &rset);
+               if(select(sfd+1, &rset, NULL, NULL, NULL) < 1) {
+                       perror("select");
+                       return 1;
+               }
+               i = 0;
+               while(i < num) {
+                       if(recv(sfd, &x, sizeof(x), 0) != sizeof(x)) {
+                               if(errno == EAGAIN)
+                                       continue;
+                               perror("recv");
+                               return 1;
+                       }
+                       i++;
+               }
+               /* now we want to get EAGAIN: nonblocking goodness */
+               errno = 0;
+               recv(sfd, &x, sizeof(x), 0);
+               if(errno != EAGAIN) {
+                       perror("trying to recv again");
+                       return 1;
+               }
+               /* EAGAIN encountered */
+       }
+
+       close(sfd);
+       close(cfd);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+       { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define NONBLOCKING_IS_BROKEN 1
+_ACEOF
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
 # check mkdir
 { echo "$as_me:$LINENO: checking whether mkdir has one arg" >&5
 echo $ECHO_N "checking whether mkdir has one arg... $ECHO_C" >&6; }
index a0c0ff8a50c2cf37bfdd600347c66a1244c0b93e..d7c26e901a7d16ad59669faab76fbc7cf86a5513 100644 (file)
@@ -802,6 +802,134 @@ if echo $build_os | grep darwin8 > /dev/null; then
        AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
 fi
 
+# check if select and nonblocking sockets actually work.
+AC_MSG_CHECKING([if nonblocking sockets work])
+AC_RUN_IFELSE(AC_LANG_PROGRAM([
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+],[[
+       int port;
+       int sfd, cfd;
+       int num = 10;
+       int i, p;
+       struct sockaddr_in a;
+       /* test if select and nonblocking reads work well together */
+       /* open port.
+          fork child to send 10 messages.
+          select to read.
+          then try to nonblocking read the 10 messages
+          then, nonblocking read must give EAGAIN
+       */
+
+       port = 12345 + (time(0)%32);
+       sfd = socket(PF_INET, SOCK_DGRAM, 0);
+       if(sfd == -1) {
+               perror("socket");
+               return 1;
+       }
+       memset(&a, 0, sizeof(a));
+       a.sin_family = AF_INET;
+       a.sin_port = htons(port);
+       a.sin_addr.s_addr = inet_addr("127.0.0.1");
+       if(bind(sfd, (struct sockaddr*)&a, sizeof(a)) < 0) {
+               perror("bind");
+               return 1;
+       }
+       if(fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) {
+               perror("fcntl");
+               return 1;
+       }
+
+       cfd = socket(PF_INET, SOCK_DGRAM, 0);
+       if(cfd == -1) {
+               perror("client socket");
+               return 1;
+       }
+       a.sin_port = 0;
+       if(bind(cfd, (struct sockaddr*)&a, sizeof(a)) < 0) {
+               perror("client bind");
+               return 1;
+       }
+       a.sin_port = htons(port);
+
+       /* no handler, causes exit in 10 seconds */
+       alarm(10);
+
+       /* send and receive on the socket */
+       if((p=fork()) == 0) {
+               for(i=0; i<num; i++) {
+                       if(sendto(cfd, &i, sizeof(i), 0, 
+                               (struct sockaddr*)&a, sizeof(a)) < 0) {
+                               perror("sendto");
+                               return 1;
+                       }
+               }
+       } else {
+               /* parent */
+               fd_set rset;
+               int x;
+               if(p == -1) {
+                       perror("fork");
+                       return 1;
+               }
+               FD_ZERO(&rset);
+               FD_SET(sfd, &rset);
+               if(select(sfd+1, &rset, NULL, NULL, NULL) < 1) {
+                       perror("select");
+                       return 1;
+               }
+               i = 0;
+               while(i < num) {
+                       if(recv(sfd, &x, sizeof(x), 0) != sizeof(x)) {
+                               if(errno == EAGAIN)
+                                       continue;
+                               perror("recv");
+                               return 1;
+                       }
+                       i++;
+               }
+               /* now we want to get EAGAIN: nonblocking goodness */
+               errno = 0;
+               recv(sfd, &x, sizeof(x), 0);
+               if(errno != EAGAIN) {
+                       perror("trying to recv again");
+                       return 1;
+               }
+               /* EAGAIN encountered */
+       }
+
+       close(sfd);
+       close(cfd);
+]]), [
+       AC_MSG_RESULT([yes])
+], [
+       AC_MSG_RESULT([no])
+       AC_DEFINE([NONBLOCKING_IS_BROKEN], 1, [Define if the network stack does not fully support nonblocking io (causes lower performance).])
+], [
+       AC_MSG_RESULT([crosscompile(yes)])
+])
+
 # check mkdir
 AC_MSG_CHECKING([whether mkdir has one arg])
 AC_TRY_COMPILE([
index 894bcc6a84a231acdfd55ca888a41bd2fc81e4e0..a38c3f243b617da1d09434cd2cbb790e80e723f1 100644 (file)
@@ -1,5 +1,6 @@
 7 November 2008: Wouter
        - fix bug 217: fixed, setreuid and setregid do not work on MacOSX10.4.
+       - detect nonblocking problems in network stack in configure script.
 
 6 November 2008: Wouter
        - dname_priv must decompress the name before comparison.
index edbd1448450823fe7da2b58c04433837be6e50e5..8fc9a576d7141a233ee5bb2894c9fb19e69ca4a5 100644 (file)
 /** The TCP reading or writing query timeout in seconds */
 #define TCP_QUERY_TIMEOUT 120 
 
+#ifndef NONBLOCKING_IS_BROKEN
 /** number of UDP reads to perform per read indication from select */
 #define NUM_UDP_PER_SELECT 100
+#else
+#define NUM_UDP_PER_SELECT 1
+#endif
 
 /* We define libevent structures here to hide the libevent stuff. */