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)
{
return plan;
}
+
+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)
+ return true;
+
+ /* Synchronous please. */
+ set_blocking(io_conn_fd(conn), true);
+
+again:
+ switch (plan->io(conn->fd.fd, &plan->arg)) {
+ case -1:
+ ok = false;
+ break;
+ /* Incomplete, try again. */
+ case 0:
+ goto again;
+ case 1:
+ ok = true;
+ /* In case they come back. */
+ set_always(conn, IO_OUT, plan->next, plan->next_arg);
+ break;
+ default:
+ /* IO should only return -1, 0 or 1 */
+ abort();
+ }
+
+ set_blocking(io_conn_fd(conn), false);
+ return ok;
+}