diff --git a/ccan/README b/ccan/README index 0698a0be7..c7b31a68d 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2338-g97ac583 +CCAN version: init-2344-g3f64234 diff --git a/ccan/ccan/io/backend.h b/ccan/ccan/io/backend.h index f57d24950..3e158a366 100644 --- a/ccan/ccan/io/backend.h +++ b/ccan/ccan/io/backend.h @@ -73,13 +73,13 @@ bool add_listener(struct io_listener *l); bool add_conn(struct io_conn *c); bool add_duplex(struct io_conn *c); void del_listener(struct io_listener *l); +void cleanup_conn_without_close(struct io_conn *c); void backend_new_always(struct io_conn *conn); void backend_new_plan(struct io_conn *conn); void remove_from_always(struct io_conn *conn); void backend_plan_done(struct io_conn *conn); void backend_wake(const void *wait); -void backend_del_conn(struct io_conn *conn); void io_ready(struct io_conn *conn, int pollflags); void io_do_always(struct io_conn *conn); diff --git a/ccan/ccan/io/io.c b/ccan/ccan/io/io.c index 4c41c93a6..68b95e824 100644 --- a/ccan/ccan/io/io.c +++ b/ccan/ccan/io/io.c @@ -421,6 +421,14 @@ struct io_plan *io_close_cb(struct io_conn *conn, void *next_arg) return io_close(conn); } +struct io_plan *io_close_taken_fd(struct io_conn *conn) +{ + set_blocking(conn->fd.fd, true); + + cleanup_conn_without_close(conn); + return io_close(conn); +} + /* Exit the loop, returning this (non-NULL) arg. */ void io_break(const void *ret) { diff --git a/ccan/ccan/io/io.h b/ccan/ccan/io/io.h index fe040bce2..1664df65f 100644 --- a/ccan/ccan/io/io.h +++ b/ccan/ccan/io/io.h @@ -109,7 +109,8 @@ void io_set_finish_(struct io_conn *conn, * @arg: the argument to @init. * * When @fd becomes readable, we accept(), create a new connection, - * (tal'ocated off @ctx) and pass that to init(). + * (tal'ocated off @ctx) and pass that to init(). Note that if there is + * an error on this file descriptor, it will be freed. * * Returns NULL on error (and sets errno). * @@ -595,14 +596,16 @@ struct io_plan *io_never(struct io_conn *conn, void *unused); /* FIXME: io_recvfrom/io_sendto */ /** - * io_close - plan to close a connection. + * io_close - close a connection. * @conn: the connection to close. * - * On return to io_loop, the connection will be closed. It doesn't have - * to be the current connection and it doesn't need to be idle. No more - * IO or callbacks will occur. + * The connection is immediately freed: it doesn't have to be the + * current connection and it doesn't need to be idle. No more IO or + * callbacks will occur, but if a function was added by io_set_finish() + * it will be called with the current errno preserved. * - * You can close a connection twice without harmful effects. + * This is equivalent to tal_free(io_conn), except it returns an io_plan + * for use in an io callback. * * Example: * static struct io_plan *close_on_timeout(struct io_conn *conn, const char *msg) @@ -617,14 +620,34 @@ struct io_plan *io_close(struct io_conn *conn); * io_close_cb - helper callback to close a connection. * @conn: the connection. * - * This schedules a connection to be closed; designed to be used as - * a callback function. + * This is closes a connection; designed to be used as a callback + * function. * * Example: * #define close_on_timeout io_close_cb */ struct io_plan *io_close_cb(struct io_conn *, void *unused); +/** + * io_close_taken_fd - close a connection, but remove the filedescriptor first. + * @conn: the connection to take the file descriptor from and close. + * + * io_close closes the file descriptor underlying the io_conn; this version does + * not. Presumably you have used io_conn_fd() on it beforehand and will take + * care of the fd yourself. + * + * Note that this also turns off O_NONBLOCK on the fd. + * + * Example: + * static struct io_plan *steal_fd(struct io_conn *conn, int *fd) + * { + * *fd = io_conn_fd(conn); + * printf("stealing fd %i and closing\n", *fd); + * return io_close_taken_fd(conn); + * } + */ +struct io_plan *io_close_taken_fd(struct io_conn *conn); + /** * io_loop - process fds until all closed on io_break. * @timers - timers which are waiting to go off (or NULL for none) @@ -643,7 +666,10 @@ void *io_loop(struct timers *timers, struct timer **expired); * io_conn_fd - get the fd from a connection. * @conn: the connection. * - * Sometimes useful, eg for getsockname(). + * Sometimes useful, eg for getsockname(). Note that the fd is O_NONBLOCK. + * + * See Also: + * io_close_taken_fd */ int io_conn_fd(const struct io_conn *conn); diff --git a/ccan/ccan/io/poll.c b/ccan/ccan/io/poll.c index 6738f720e..043feff74 100644 --- a/ccan/ccan/io/poll.c +++ b/ccan/ccan/io/poll.c @@ -86,13 +86,6 @@ static void del_fd(struct fd *fd) } num_fds--; fd->backend_info = -1; - - /* Closing a local socket doesn't wake poll() because other end - * has them open. See 2.6. When should I use shutdown()? - * in http://www.faqs.org/faqs/unix-faq/socket/ */ - shutdown(fd->fd, SHUT_RDWR); - - close(fd->fd); } static void destroy_listener(struct io_listener *l) @@ -164,11 +157,12 @@ void backend_wake(const void *wait) } } -static void destroy_conn(struct io_conn *conn) +static void destroy_conn(struct io_conn *conn, bool close_fd) { int saved_errno = errno; - close(conn->fd.fd); + if (close_fd) + close(conn->fd.fd); del_fd(&conn->fd); /* In case it's on always list, remove it. */ list_del_init(&conn->always); @@ -180,14 +174,25 @@ static void destroy_conn(struct io_conn *conn) } } +static void destroy_conn_close_fd(struct io_conn *conn) +{ + destroy_conn(conn, true); +} + bool add_conn(struct io_conn *c) { if (!add_fd(&c->fd, 0)) return false; - tal_add_destructor(c, destroy_conn); + tal_add_destructor(c, destroy_conn_close_fd); return true; } +void cleanup_conn_without_close(struct io_conn *conn) +{ + tal_del_destructor(conn, destroy_conn_close_fd); + destroy_conn(conn, false); +} + static void accept_conn(struct io_listener *l) { int fd = accept(l->fd.fd, NULL, NULL); @@ -276,9 +281,14 @@ void *io_loop(struct timers *timers, struct timer **expired) break; if (fds[i]->listener) { + struct io_listener *l = (void *)fds[i]; if (events & POLLIN) { - accept_conn((void *)c); + accept_conn(l); + r--; + } else if (events & (POLLHUP|POLLNVAL|POLLERR)) { r--; + errno = EBADF; + io_close_listener(l); } } else if (events & (POLLIN|POLLOUT)) { r--; diff --git a/ccan/ccan/str/str.h b/ccan/ccan/str/str.h index 85491bc7e..d919b84d4 100644 --- a/ccan/ccan/str/str.h +++ b/ccan/ccan/str/str.h @@ -94,7 +94,7 @@ size_t strcount(const char *haystack, const char *needle); #if HAVE_TYPEOF /* Only a simple type can have 0 assigned, so test that. */ #define STR_MAX_CHARS_TCHECK_(type_or_expr) \ - ({ typeof(type_or_expr) x = 0; (void)x; 0; }) + (sizeof(({ typeof(type_or_expr) x = 0; x; }))*0) #else #define STR_MAX_CHARS_TCHECK_(type_or_expr) 0 #endif