diff --git a/ccan/README b/ccan/README index a22f01b20..fb5efa185 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2393-g9728f1d9 +CCAN version: init-2397-g261b1086 diff --git a/ccan/ccan/endian/endian.h b/ccan/ccan/endian/endian.h index 0c99cc802..6732e8aa8 100644 --- a/ccan/ccan/endian/endian.h +++ b/ccan/ccan/endian/endian.h @@ -103,13 +103,22 @@ static inline uint64_t bswap_64(uint64_t val) } #endif +/* Needed for Glibc like endiness check */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + /* Sanity check the defines. We don't handle weird endianness. */ #if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN #error "Unknown endian" #elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN #error "Can't compile for both big and little endian." +#elif HAVE_LITTLE_ENDIAN +#define __BYTE_ORDER __LITTLE_ENDIAN +#elif HAVE_BIG_ENDIAN +#define __BYTE_ORDER __BIG_ENDIAN #endif + #ifdef __CHECKER__ /* sparse needs forcing to remove bitwise attribute from ccan/short_types */ #define ENDIAN_CAST __attribute__((force)) diff --git a/ccan/ccan/io/_info b/ccan/ccan/io/_info index fe49df5c8..6e95e4ab9 100644 --- a/ccan/ccan/io/_info +++ b/ccan/ccan/io/_info @@ -61,9 +61,10 @@ * { * // Remove what we just wrote. * b->start += b->wlen; + * b->wlen = 0; * assert(b->start <= sizeof(b->buf)); * - * // If we wrote something, wake writer. + * // If we wrote something, wake reader. * if (b->wlen != 0) * io_wake(b); * @@ -114,6 +115,7 @@ * io_new_conn(NULL, tochild[1], write_out, &to); * * // Read from child, write to stdout. + * memset(&from, 0, sizeof(from)); * reader = io_new_conn(NULL, fromchild[0], read_in, &from); * io_set_finish(reader, finish, &from); * io_new_conn(NULL, STDOUT_FILENO, write_out, &from); diff --git a/ccan/ccan/io/io.c b/ccan/ccan/io/io.c index cc2b1afa3..99f0f7c90 100644 --- a/ccan/ccan/io/io.c +++ b/ccan/ccan/io/io.c @@ -363,14 +363,20 @@ void io_wake(const void *wait) backend_wake(wait); } -/* Returns false if this has been freed. */ -static bool do_plan(struct io_conn *conn, struct io_plan *plan) +/* Returns false if this should not be touched (eg. freed). */ +static bool do_plan(struct io_conn *conn, struct io_plan *plan, + bool idle_on_epipe) { /* We shouldn't have polled for this event if this wasn't true! */ assert(plan->status == IO_POLLING); switch (plan->io(conn->fd.fd, &plan->arg)) { case -1: + if (errno == EPIPE && idle_on_epipe) { + plan->status = IO_UNSET; + backend_new_plan(conn); + return false; + } io_close(conn); return false; case 0: @@ -386,11 +392,14 @@ static bool do_plan(struct io_conn *conn, struct io_plan *plan) void io_ready(struct io_conn *conn, int pollflags) { if (pollflags & POLLIN) - if (!do_plan(conn, &conn->plan[IO_IN])) + if (!do_plan(conn, &conn->plan[IO_IN], false)) return; if (pollflags & POLLOUT) - do_plan(conn, &conn->plan[IO_OUT]); + /* If we're writing to a closed pipe, we need to wait for + * read to fail if we're duplex: we want to drain it! */ + do_plan(conn, &conn->plan[IO_OUT], + conn->plan[IO_IN].status == IO_POLLING); } void io_do_always(struct io_conn *conn)