From: Rusty Russell Date: Mon, 14 Oct 2013 10:58:36 +0000 (+1030) Subject: ccan/io: test read after hangup. X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=cf86c1e30648c9b482b92444c39ea6ea0ff936a8 ccan/io: test read after hangup. In particular, make sure that idle connections don't get closed. Signed-off-by: Rusty Russell --- diff --git a/ccan/io/poll.c b/ccan/io/poll.c index 9f9bb4a2..7f3df7ed 100644 --- a/ccan/io/poll.c +++ b/ccan/io/poll.c @@ -31,8 +31,12 @@ static bool add_fd(struct fd *fd, short events) max_fds = num; } - pollfds[num_fds].fd = fd->fd; pollfds[num_fds].events = events; + /* In case it's idle. */ + if (!events) + pollfds[num_fds].fd = -fd->fd; + else + pollfds[num_fds].fd = fd->fd; pollfds[num_fds].revents = 0; /* In case we're iterating now */ fds[num_fds] = fd; fd->backend_info = num_fds; @@ -91,8 +95,11 @@ void backend_plan_changed(struct io_conn *conn) assert(!mask || pfd->events != mask); pfd->events |= mask; } - if (pfd->events) + if (pfd->events) { num_waiting++; + pfd->fd = conn->fd.fd; + } else + pfd->fd = -conn->fd.fd; if (!conn->plan.next) num_closing++; diff --git a/ccan/io/test/run-08-hangup-on-idle.c b/ccan/io/test/run-08-hangup-on-idle.c new file mode 100644 index 00000000..364d7943 --- /dev/null +++ b/ccan/io/test/run-08-hangup-on-idle.c @@ -0,0 +1,45 @@ +#include +/* Include the C files directly. */ +#include +#include +#include +#include +#include + +static int fds2[2]; + +static struct io_plan timeout_wakeup(struct io_conn *conn, char *buf) +{ + /* This kills the dummy connection. */ + close(fds2[1]); + return io_read(buf, 16, io_close, NULL); +} + +int main(void) +{ + int fds[2]; + struct io_conn *conn; + char buf[16]; + + plan_tests(4); + + ok1(pipe(fds) == 0); + + /* Write then close. */ + io_new_conn(fds[1], io_write("hello there world", 16, io_close, NULL), + NULL, NULL); + conn = io_new_conn(fds[0], io_idle(), NULL, NULL); + + /* To avoid assert(num_waiting) */ + ok1(pipe(fds2) == 0); + io_new_conn(fds2[0], io_read(buf, 16, io_close, NULL), NULL, NULL); + + /* After half a second, it will read. */ + io_timeout(conn, time_from_msec(500), timeout_wakeup, buf); + + ok1(io_loop() == NULL); + ok1(memcmp(buf, "hello there world", 16) == 0); + + /* This exits depending on whether all tests passed */ + return exit_status(); +} diff --git a/ccan/io/test/run-08-read-after-hangup.c b/ccan/io/test/run-08-read-after-hangup.c new file mode 100644 index 00000000..95eb651c --- /dev/null +++ b/ccan/io/test/run-08-read-after-hangup.c @@ -0,0 +1,35 @@ +#include +/* Include the C files directly. */ +#include +#include +#include +#include +#include +#include + +static char inbuf[8]; + +static struct io_plan wake_it(struct io_conn *conn, struct io_conn *reader) +{ + io_wake(reader, io_read(inbuf, 8, io_close, NULL)); + return io_close(conn, NULL); +} + +int main(void) +{ + int fds[2]; + struct io_conn *conn; + + plan_tests(3); + + ok1(pipe(fds) == 0); + conn = io_new_conn(fds[0], io_idle(), NULL, NULL); + io_new_conn(fds[1], io_write("EASYTEST", 8, wake_it, conn), + NULL, NULL); + + ok1(io_loop() == NULL); + ok1(memcmp(inbuf, "EASYTEST", sizeof(inbuf)) == 0); + + /* This exits depending on whether all tests passed */ + return exit_status(); +}