3860. [bug] ioctl(DP_POLL) array size needs to be determined

at run time as it is limited to {OPEN_MAX}.
                        [RT #35878]

(cherry picked from commit a569e1b321)
This commit is contained in:
Mark Andrews 2014-05-23 13:05:23 +10:00
parent a4b09947f6
commit 8fd8dd56fe
2 changed files with 87 additions and 25 deletions

View file

@ -1,3 +1,7 @@
3860. [bug] ioctl(DP_POLL) array size needs to be determined
at run time as it is limited to {OPEN_MAX}.
[RT #35878]
3858. [bug] Disable GCC 4.9 "delete null pointer check".
[RT #35968]

View file

@ -58,6 +58,7 @@
#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>
@ -402,6 +403,8 @@ struct isc__socketmgr {
#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 */
@ -1168,8 +1171,6 @@ select_readmsg(isc__socketmgr_t *mgr, int *fd, int *msg) {
"read() failed "
"during watcher poke: %s"),
strbuf);
return;
}
INSIST(cc == sizeof(buf));
@ -4098,8 +4099,10 @@ watcher(void *uap) {
#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;
@ -4126,17 +4129,45 @@ watcher(void *uap) {
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,
@ -4296,11 +4327,12 @@ setup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) {
}
#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)
@ -6149,8 +6181,6 @@ isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp,
isc_socketwait_t **swaitp)
{
isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
int n;
#ifdef USE_KQUEUE
struct timespec ts, *tsp;
@ -6159,6 +6189,8 @@ isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp,
int timeout;
#endif
#ifdef USE_DEVPOLL
isc_result_t result;
int pass;
struct dvpoll dvp;
#endif
@ -6192,15 +6224,41 @@ isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp,
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,