int flux_pollfd (flux_t h) { if (h->pollfd < 0) { struct epoll_event ev = { .events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP, }; if ((h->pollfd = epoll_create1 (EPOLL_CLOEXEC)) < 0) goto fatal; /* add queue pollfd */ ev.data.fd = msglist_pollfd (h->queue); if (ev.data.fd < 0) goto fatal; if (epoll_ctl (h->pollfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0) goto fatal; /* add connector pollfd (if defined) */ if (h->ops->pollfd) { ev.data.fd = h->ops->pollfd (h->impl); if (ev.data.fd < 0) goto fatal; if (epoll_ctl (h->pollfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0) goto fatal; } } return h->pollfd; fatal: if (h->pollfd >= 0) { (void)close (h->pollfd); h->pollfd = -1; } FLUX_FATAL (h); return -1; } int flux_pollevents (flux_t h) { int e, events = 0; /* wait for handle event */ if (h->pollfd >= 0) { struct epoll_event ev; (void)epoll_wait (h->pollfd, &ev, 1, 0); } /* get connector events (if applicable) */ if (h->ops->pollevents) { if ((events = h->ops->pollevents (h->impl)) < 0) goto fatal; } /* get queue events */ if ((e = msglist_pollevents (h->queue)) < 0) goto fatal; if ((e & POLLIN)) events |= FLUX_POLLIN; if ((e & POLLOUT)) events |= FLUX_POLLOUT; if ((e & POLLERR)) events |= FLUX_POLLERR; return events; fatal: FLUX_FATAL (h); return -1; }
static int op_pollfd (void *impl) { ctx_t *c = impl; return msglist_pollfd (c->queue); }
int main (int argc, char *argv[]) { msglist_t *ml; int e; char *msg; struct pollfd pfd; plan (19); ok ((ml = msglist_create (free)) != NULL, "msglist_create works"); ok ((e = msglist_pollevents (ml)) >= 0 && e == POLLOUT, "msglist_pollevents on empty msglist returns POLLOUT"); ok (msglist_append (ml, xstrdup ("foo")) == 0, "msglist_append 'foo' works"); ok ((e = msglist_pollevents (ml)) >= 0 && e == (POLLOUT | POLLIN), "msglist_pollevents on non-empty msglist returns POLLOUT | POLLIN"); ok (msglist_push (ml, xstrdup ("bar")) == 0, "msglist_push 'bar' works"); ok ((e = msglist_pollevents (ml)) >= 0 && e == (POLLOUT | POLLIN), "msglist_pollevents still returns POLLOUT | POLLIN"); ok ((msg = msglist_pop (ml)) != NULL && !strcmp (msg, "bar"), "msglist_pop returns 'bar'"); ok ((e = msglist_pollevents (ml)) >= 0 && e == (POLLOUT | POLLIN), "msglist_pollevents still returns POLLOUT | POLLIN"); free (msg); ok ((msg = msglist_pop (ml)) != NULL && !strcmp (msg, "foo"), "msglist_pop returns 'foo'"); ok ((e = msglist_pollevents (ml)) >= 0 && e == POLLOUT, "msglist_pollevents on empty msglist returns POLLOUT"); free (msg); ok ((pfd.fd = msglist_pollfd (ml)) >= 0, "msglist_pollfd works"); pfd.events = POLLIN, pfd.revents = 0, ok (poll (&pfd, 1, 0) == 1 && pfd.revents == POLLIN, "pollfd suggests we read pollevents"); ok ((e = msglist_pollevents (ml)) >= 0 && e == POLLOUT, "msglist_pollevents on empty msglist returns POLLOUT"); pfd.events = POLLIN, pfd.revents = 0, ok (poll (&pfd, 1, 0) == 0, "pollfd is no longer ready"); ok (msglist_push (ml, xstrdup ("foo")) == 0, "msglist_push 'foo' works"); pfd.events = POLLIN, pfd.revents = 0, ok (poll (&pfd, 1, 0) == 1 && pfd.revents == POLLIN, "pollfd suggests we read pollevents"); ok ((e = msglist_pollevents (ml)) >= 0 && e == (POLLOUT | POLLIN), "msglist_pollevents on non-empty msglist returns POLLOUT | POLLIN"); pfd.events = POLLIN, pfd.revents = 0, ok (poll (&pfd, 1, 0) == 0, "pollfd is no longer ready"); ok ((e = msglist_pollevents (ml)) >= 0 && e == (POLLOUT | POLLIN), "msglist_pollevents still returns POLLOUT | POLLIN"); msglist_destroy (ml); done_testing (); return (0); }