X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fio%2Fpoll.c;h=31a56600fe487b836e8bf1b8bdb88ecfa75953e0;hp=85407f62a8e32bafef27bb735b31992b3c1d2c66;hb=641b511049e5c03d45ada0c3fd829691b173e5d1;hpb=34776d3e9ad7de78778306a2d09c2c95df06c902 diff --git a/ccan/io/poll.c b/ccan/io/poll.c index 85407f62..31a56600 100644 --- a/ccan/io/poll.c +++ b/ccan/io/poll.c @@ -7,6 +7,7 @@ #include #include #include +#include static size_t num_fds = 0, max_fds = 0, num_closing = 0, num_waiting = 0; static struct pollfd *pollfds = NULL; @@ -171,10 +172,12 @@ bool add_duplex(struct io_conn *c) return true; } -static void del_conn(struct io_conn *conn) +void backend_del_conn(struct io_conn *conn) { - if (conn->finish) + if (conn->finish) { + errno = conn->plan.u.close.saved_errno; conn->finish(conn, conn->finish_arg); + } if (timeout_active(conn)) backend_del_timeout(conn); free(conn->timeout); @@ -186,6 +189,7 @@ static void del_conn(struct io_conn *conn) } else del_fd(&conn->fd); num_closing--; + free_conn(conn); } void del_listener(struct io_listener *l) @@ -210,7 +214,7 @@ static void accept_conn(struct io_listener *l) } /* It's OK to miss some, as long as we make progress. */ -static void finish_conns(void) +static bool finish_conns(struct io_conn **ready) { unsigned int i; @@ -225,12 +229,16 @@ static void finish_conns(void) c = (void *)fds[i]; for (duplex = c->duplex; c; c = duplex, duplex = NULL) { if (!c->plan.next) { - del_conn(c); - free_conn(c); + if (doing_debug_on(c) && ready) { + *ready = c; + return true; + } + backend_del_conn(c); i--; } } } + return false; } void backend_add_timeout(struct io_conn *conn, struct timespec duration) @@ -250,7 +258,7 @@ void backend_del_timeout(struct io_conn *conn) } /* This is the main loop. */ -void *io_loop(void) +void *do_io_loop(struct io_conn **ready) { void *ret; @@ -288,7 +296,9 @@ void *io_loop(void) } if (num_closing) { - finish_conns(); + /* If this finishes a debugging con, return now. */ + if (finish_conns(ready)) + return NULL; /* Could have started/finished more. */ continue; } @@ -324,6 +334,11 @@ void *io_loop(void) if (c->duplex) { int mask = c->duplex->plan.pollflag; if (events & mask) { + if (doing_debug_on(c->duplex) + && ready) { + *ready = c->duplex; + return NULL; + } io_ready(c->duplex); events &= ~mask; /* debug can recurse; @@ -334,25 +349,31 @@ void *io_loop(void) continue; } } + if (doing_debug_on(c) && ready) { + *ready = c; + return NULL; + } io_ready(c); /* debug can recurse; anything can change. */ if (doing_debug()) break; - } else if (events & POLLHUP) { + } else if (events & (POLLHUP|POLLNVAL|POLLERR)) { r--; set_current(c); - set_plan(c, io_close(c, NULL)); + errno = EBADF; + set_plan(c, io_close()); if (c->duplex) { set_current(c->duplex); - set_plan(c->duplex, - io_close(c->duplex, NULL)); + set_plan(c->duplex, io_close()); } } } } - while (num_closing) - finish_conns(); + while (num_closing && !io_loop_return) { + if (finish_conns(ready)) + return NULL; + } ret = io_loop_return; io_loop_return = NULL; @@ -360,3 +381,8 @@ void *io_loop(void) io_loop_exit(); return ret; } + +void *io_loop(void) +{ + return do_io_loop(NULL); +}