static isc_threadresult_t
watcher(void *uap) {
isc__socketmgr_t *manager = uap;
isc_boolean_t done;
int ctlfd;
int cc;
#ifdef USE_KQUEUE
const char *fnname = "kevent()";
#elif defined (USE_EPOLL)
const char *fnname = "epoll_wait()";
#elif defined(USE_DEVPOLL)
const char *fnname = "ioctl(DP_POLL)";
struct dvpoll dvp;
#elif defined (USE_SELECT)
const char *fnname = "select()";
int maxfd;
#endif
char strbuf[ISC_STRERRORSIZE];
#ifdef ISC_SOCKET_USE_POLLWATCH
pollstate_t pollstate = poll_idle;
#endif
/*
* Get the control fd here. This will never change.
*/
ctlfd = manager->pipe_fds[0];
done = ISC_FALSE;
while (!done) {
do {
#ifdef USE_KQUEUE
cc = kevent(manager->kqueue_fd, NULL, 0,
manager->events, manager->nevents, NULL);
#elif defined(USE_EPOLL)
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;
#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;
#endif /* ISC_SOCKET_USE_POLLWATCH */
cc = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
#elif defined(USE_SELECT)
LOCK(&manager->lock);
memcpy(manager->read_fds_copy, manager->read_fds,
manager->fd_bufsize);
memcpy(manager->write_fds_copy, manager->write_fds,
manager->fd_bufsize);
maxfd = manager->maxfd + 1;
UNLOCK(&manager->lock);
cc = select(maxfd, manager->read_fds_copy,
manager->write_fds_copy, NULL, NULL);
#endif /* USE_KQUEUE */
if (cc < 0 && !SOFT_ERROR(errno)) {
isc__strerror(errno, strbuf, sizeof(strbuf));
FATAL_ERROR(__FILE__, __LINE__,
"%s %s: %s", fnname,
isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
ISC_MSG_FAILED,
"failed"), strbuf);
}
#if defined(USE_DEVPOLL) && defined(ISC_SOCKET_USE_POLLWATCH)
if (cc == 0) {
if (pollstate == poll_active)
pollstate = poll_checking;
else if (pollstate == poll_checking)
pollstate = poll_idle;
} else if (cc > 0) {
if (pollstate == poll_checking) {
/*
* XXX: We'd like to use a more
* verbose log level as it's actually an
* unexpected event, but the kernel bug
* reportedly happens pretty frequently
* (and it can also be a false positive)
* so it would be just too noisy.
*/
manager_log(manager,
ISC_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_SOCKET,
ISC_LOG_DEBUG(1),
"unexpected POLL timeout");
}
pollstate = poll_active;
}
#endif
} while (cc < 0);
#if defined(USE_KQUEUE) || defined (USE_EPOLL) || defined (USE_DEVPOLL)
done = process_fds(manager, manager->events, cc);
#elif defined(USE_SELECT)
process_fds(manager, maxfd, manager->read_fds_copy,
manager->write_fds_copy);
/*
* Process reads on internal, control fd.
*/
if (FD_ISSET(ctlfd, manager->read_fds_copy))
done = process_ctlfd(manager);
#endif
}
manager_log(manager, TRACE, "%s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_EXITING, "watcher exiting"));
return ((isc_threadresult_t)0);
}