X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Fio%2Fio.c;h=bdcbf9e26b8f9f580fea08c2c0913d31efe9dcc7;hb=9f06b8f85927202c05751e43f285cbef8054052b;hp=7eea9c35442cbbcb4386b430929195d1454b49a0;hpb=e2e70f5566cb8978b74de517c24a0f236d3d01ee;p=ccan diff --git a/ccan/io/io.c b/ccan/io/io.c index 7eea9c35..bdcbf9e2 100644 --- a/ccan/io/io.c +++ b/ccan/io/io.c @@ -131,7 +131,7 @@ struct io_plan_arg *io_plan_arg(struct io_conn *conn, enum io_direction dir) { assert(conn->plan[dir].status == IO_UNSET); - conn->plan[dir].status = IO_POLLING; + conn->plan[dir].status = IO_POLLING_NOTSTARTED; return &conn->plan[dir].arg; } @@ -202,8 +202,12 @@ struct io_plan *io_write_(struct io_conn *conn, const void *data, size_t len, static int do_read(int fd, struct io_plan_arg *arg) { ssize_t ret = read(fd, arg->u1.cp, arg->u2.s); - if (ret <= 0) + if (ret <= 0) { + /* Errno isn't set if we hit EOF, so set it to distinct value */ + if (ret == 0) + errno = 0; return -1; + } arg->u1.cp += ret; arg->u2.s -= ret; @@ -230,8 +234,12 @@ struct io_plan *io_read_(struct io_conn *conn, static int do_read_partial(int fd, struct io_plan_arg *arg) { ssize_t ret = read(fd, arg->u1.cp, *(size_t *)arg->u2.vp); - if (ret <= 0) + if (ret <= 0) { + /* Errno isn't set if we hit EOF, so set it to distinct value */ + if (ret == 0) + errno = 0; return -1; + } *(size_t *)arg->u2.vp = ret; return 1; @@ -368,7 +376,8 @@ 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); + assert(plan->status == IO_POLLING_NOTSTARTED + || plan->status == IO_POLLING_STARTED); switch (plan->io(conn->fd.fd, &plan->arg)) { case -1: @@ -380,6 +389,7 @@ static bool do_plan(struct io_conn *conn, struct io_plan *plan, io_close(conn); return false; case 0: + plan->status = IO_POLLING_STARTED; return true; case 1: return next_plan(conn, plan); @@ -399,8 +409,8 @@ void io_ready(struct io_conn *conn, int pollflags) /* 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 - || conn->plan[IO_IN].status == IO_ALWAYS)); + conn->plan[IO_IN].status == IO_POLLING_NOTSTARTED + || conn->plan[IO_IN].status == IO_POLLING_STARTED); } void io_do_always(struct io_conn *conn) @@ -510,13 +520,24 @@ struct io_plan *io_set_plan(struct io_conn *conn, enum io_direction dir, return plan; } +bool io_plan_in_started(const struct io_conn *conn) +{ + return conn->plan[IO_IN].status == IO_POLLING_STARTED; +} + +bool io_plan_out_started(const struct io_conn *conn) +{ + return conn->plan[IO_OUT].status == IO_POLLING_STARTED; +} + bool io_flush_sync(struct io_conn *conn) { struct io_plan *plan = &conn->plan[IO_OUT]; bool ok; /* Not writing? Nothing to do. */ - if (plan->status != IO_POLLING) + if (plan->status != IO_POLLING_STARTED + && plan->status != IO_POLLING_NOTSTARTED) return true; /* Synchronous please. */ @@ -529,6 +550,7 @@ again: break; /* Incomplete, try again. */ case 0: + plan->status = IO_POLLING_STARTED; goto again; case 1: ok = true;