#include <isc/platform.h>
#include <isc/print.h>
#include <isc/region.h>
+#include <isc/resource.h>
#include <isc/socket.h>
#include <isc/stats.h>
#include <isc/strerror.h>
#endif /* USE_EPOLL */
#ifdef USE_DEVPOLL
int devpoll_fd;
+ isc_resourcevalue_t open_max;
+ unsigned int calls;
int nevents;
struct pollfd *events;
#endif /* USE_DEVPOLL */
"read() failed "
"during watcher poke: %s"),
strbuf);
-
- return;
}
INSIST(cc == sizeof(buf));
#elif defined (USE_EPOLL)
const char *fnname = "epoll_wait()";
#elif defined(USE_DEVPOLL)
+ isc_result_t result;
const char *fnname = "ioctl(DP_POLL)";
struct dvpoll dvp;
+ int pass;
#elif defined (USE_SELECT)
const char *fnname = "select()";
int maxfd;
cc = epoll_wait(manager->epoll_fd, manager->events,
manager->nevents, -1);
#elif defined(USE_DEVPOLL)
- dvp.dp_fds = manager->events;
- dvp.dp_nfds = manager->nevents;
+ /*
+ * Re-probe every thousand calls.
+ */
+ if (manager->calls++ > 1000U) {
+ result = isc_resource_getcurlimit(
+ isc_resource_openfiles,
+ &manager->open_max);
+ if (result != ISC_R_SUCCESS)
+ manager->open_max = 64;
+ manager->calls == 0;
+ }
+ for (pass = 0; pass < 2; pass++) {
+ dvp.dp_fds = manager->events;
+ dvp.dp_nfds = manager->nevents;
+ if (dvp.dp_nfds >= manager->open_max)
+ dvp.dp_nfds = manager->open_max - 1;
#ifndef ISC_SOCKET_USE_POLLWATCH
- dvp.dp_timeout = -1;
-#else
- if (pollstate == poll_idle)
dvp.dp_timeout = -1;
- else
- dvp.dp_timeout = ISC_SOCKET_POLLWATCH_TIMEOUT;
+#else
+ if (pollstate == poll_idle)
+ dvp.dp_timeout = -1;
+ else
+ dvp.dp_timeout =
+ ISC_SOCKET_POLLWATCH_TIMEOUT;
#endif /* ISC_SOCKET_USE_POLLWATCH */
- cc = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
+ cc = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
+ if (cc == -1 && errno == EINVAL) {
+ /*
+ * {OPEN_MAX} may have dropped. Look
+ * up the current value and try again.
+ */
+ result = isc_resource_getcurlimit(
+ isc_resource_openfiles,
+ &manager->open_max);
+ if (result != ISC_R_SUCCESS)
+ manager->open_max = 64;
+ } else
+ break;
+ }
#elif defined(USE_SELECT)
LOCK(&manager->lock);
memmove(manager->read_fds_copy, manager->read_fds,
}
#endif /* USE_WATCHER_THREAD */
#elif defined(USE_DEVPOLL)
- /*
- * XXXJT: /dev/poll seems to reject large numbers of events,
- * so we should be careful about redefining ISC_SOCKET_MAXEVENTS.
- */
manager->nevents = ISC_SOCKET_MAXEVENTS;
+ result = isc_resource_getcurlimit(isc_resource_openfiles,
+ &manager->open_max);
+ if (result != ISC_R_SUCCESS)
+ manager->open_max = 64;
+ manager->calls = 0;
manager->events = isc_mem_get(mctx, sizeof(struct pollfd) *
manager->nevents);
if (manager->events == NULL)
isc_socketwait_t **swaitp)
{
isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
-
-
int n;
#ifdef USE_KQUEUE
struct timespec ts, *tsp;
int timeout;
#endif
#ifdef USE_DEVPOLL
+ isc_result_t result;
+ int pass;
struct dvpoll dvp;
#endif
manager->nevents, timeout);
n = swait_private.nevents;
#elif defined(USE_DEVPOLL)
- dvp.dp_fds = manager->events;
- dvp.dp_nfds = manager->nevents;
- if (tvp != NULL) {
- dvp.dp_timeout = tvp->tv_sec * 1000 +
- (tvp->tv_usec + 999) / 1000;
- } else
- dvp.dp_timeout = -1;
- swait_private.nevents = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
- n = swait_private.nevents;
+ /*
+ * Re-probe every thousand calls.
+ */
+ if (manager->calls++ > 1000U) {
+ result = isc_resource_getcurlimit(isc_resource_openfiles,
+ &manager->open_max);
+ if (result != ISC_R_SUCCESS)
+ manager->open_max = 64;
+ manager->calls == 0;
+ }
+ for (pass = 0; pass < 2; pass++) {
+ dvp.dp_fds = manager->events;
+ dvp.dp_nfds = manager->nevents;
+ if (dvp.dp_nfds >= manager->open_max)
+ dvp.dp_nfds = manager->open_max - 1;
+ if (tvp != NULL) {
+ dvp.dp_timeout = tvp->tv_sec * 1000 +
+ (tvp->tv_usec + 999) / 1000;
+ } else
+ dvp.dp_timeout = -1;
+ n = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
+ if (n == -1 && errno == EINVAL) {
+ /*
+ * {OPEN_MAX} may have dropped. Look
+ * up the current value and try again.
+ */
+ result = isc_resource_getcurlimit(
+ isc_resource_openfiles,
+ &manager->open_max);
+ if (result != ISC_R_SUCCESS)
+ manager->open_max = 64;
+ } else
+ break;
+ }
+ swait_private.nevents = n;
#elif defined(USE_SELECT)
memmove(manager->read_fds_copy, manager->read_fds, manager->fd_bufsize);
memmove(manager->write_fds_copy, manager->write_fds,