From 02388bfc242abbd33c7ba64b2c32d425f5359b67 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 14 Oct 2013 21:28:35 +1030 Subject: [PATCH] ccan/io: check for all idle. It's probably a bug if we're waiting for nothing. Signed-off-by: Rusty Russell --- ccan/io/poll.c | 15 ++++++++++++-- ccan/io/test/run-13-all-idle.c | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 ccan/io/test/run-13-all-idle.c diff --git a/ccan/io/poll.c b/ccan/io/poll.c index fdff271c..7ceb8a7e 100644 --- a/ccan/io/poll.c +++ b/ccan/io/poll.c @@ -7,7 +7,7 @@ #include #include -static size_t num_fds = 0, max_fds = 0, num_next = 0, num_finished = 0; +static size_t num_fds = 0, max_fds = 0, num_next = 0, num_finished = 0, num_waiting = 0; static struct pollfd *pollfds = NULL; static struct fd **fds = NULL; @@ -65,7 +65,10 @@ static void del_fd(struct fd *fd) bool add_listener(struct io_listener *l) { - return add_fd(&l->fd, POLLIN); + if (!add_fd(&l->fd, POLLIN)) + return false; + num_waiting++; + return true; } bool add_conn(struct io_conn *c) @@ -123,6 +126,9 @@ void backend_set_state(struct io_conn *conn, struct io_op *op) enum io_state state = from_ioop(op); struct pollfd *pfd = &pollfds[conn->fd.backend_info]; + if (pfd->events) + num_waiting--; + pfd->events = pollmask(state); if (conn->duplex) { int mask = pollmask(conn->duplex->state); @@ -130,6 +136,8 @@ void backend_set_state(struct io_conn *conn, struct io_op *op) assert(!mask || pfd->events != mask); pfd->events |= mask; } + if (pfd->events) + num_waiting++; if (state == NEXT) num_next++; @@ -206,6 +214,9 @@ void *io_loop(void) if (num_fds == 0) break; + /* You can't tell them all to go to sleep! */ + assert(num_waiting); + r = poll(pollfds, num_fds, -1); if (r < 0) break; diff --git a/ccan/io/test/run-13-all-idle.c b/ccan/io/test/run-13-all-idle.c new file mode 100644 index 00000000..b6a52a55 --- /dev/null +++ b/ccan/io/test/run-13-all-idle.c @@ -0,0 +1,36 @@ +#include +/* Include the C files directly. */ +#include +#include +#include +#include +#include +#include + +static struct io_op *start(struct io_conn *conn, void *unused) +{ + return io_idle(conn); +} + +int main(void) +{ + int status; + + plan_tests(3); + + if (fork() == 0) { + int fds[2]; + + ok1(pipe(fds) == 0); + io_new_conn(fds[0], start, NULL, NULL); + io_loop(); + exit(1); + } + + ok1(wait(&status) != -1); + ok1(WIFSIGNALED(status)); + ok1(WTERMSIG(status) == SIGABRT); + + /* This exits depending on whether all tests passed */ + return exit_status(); +} -- 2.39.2