summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Kjellerstedt <peter.kjellerstedt@axis.com>2008-01-11 09:03:27 +0000
committerPeter Kjellerstedt <peter.kjellerstedt@axis.com>2008-01-11 09:03:27 +0000
commite4f07e7d1b9c6b2eab58fdebd3b9031f361d59aa (patch)
treeaa453fbe2eda27ed1b993931c8e811d17a0b622f
parent3a59892925d185dbfd2d3c3b15e1fcfac0848625 (diff)
Use poll() rather than select() if the former is available to wait in
__dns_lookup(). This avoids segmentation faults when more than 1024 file descriptors are used by an application.
-rw-r--r--libc/inet/resolv.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 591106a24..5df8fecaa 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -140,6 +140,7 @@
#include <stdio.h>
#include <signal.h>
#include <errno.h>
+#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -157,6 +158,14 @@
#include <sys/un.h>
#include <bits/uClibc_mutex.h>
+/* poll() is not supported in kernel <= 2.0, therefore if __NR_poll is
+ * not available, we assume an old Linux kernel is in use and we will
+ * use select() instead. */
+#include <sys/syscall.h>
+#ifndef __NR_poll
+# define USE_SELECT
+#endif
+
__UCLIBC_MUTEX_EXTERN(__resolv_lock);
libc_hidden_proto(memcpy)
@@ -185,6 +194,7 @@ libc_hidden_proto(inet_aton)
libc_hidden_proto(inet_pton)
libc_hidden_proto(inet_ntop)
libc_hidden_proto(connect)
+libc_hidden_proto(poll)
libc_hidden_proto(select)
libc_hidden_proto(recv)
libc_hidden_proto(send)
@@ -721,8 +731,12 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
unsigned char **outpacket, struct resolv_answer *a)
{
int i, j, len, fd, pos, rc;
+#ifdef USE_SELECT
struct timeval tv;
fd_set fds;
+#else
+ struct pollfd fds;
+#endif
struct resolv_header h;
struct resolv_question q;
struct resolv_answer ma;
@@ -851,6 +865,7 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
send(fd, packet, len, 0);
+#ifdef USE_SELECT
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = REPLY_TIMEOUT;
@@ -862,6 +877,17 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
* to next nameserver on queue */
goto tryall;
}
+#else
+ fds.fd = fd;
+ fds.events = POLLIN;
+ if (poll(&fds, 1, REPLY_TIMEOUT * 1000) <= 0) {
+ DPRINTF("Timeout\n");
+
+ /* timed out, so retry send and receive,
+ * to next nameserver on queue */
+ goto tryall;
+ }
+#endif
len = recv(fd, packet, 512, 0);
if (len < HFIXEDSZ) {