| 590 | } |
| 591 | |
| 592 | bool io_flush_sync(struct io_conn *conn) |
| 593 | { |
| 594 | struct io_plan *plan = &conn->plan[IO_OUT]; |
| 595 | bool ok; |
| 596 | |
| 597 | /* Not writing? Nothing to do. */ |
| 598 | if (plan->status != IO_POLLING_STARTED |
| 599 | && plan->status != IO_POLLING_NOTSTARTED) |
| 600 | return true; |
| 601 | |
| 602 | /* Synchronous please. */ |
| 603 | io_fd_block(io_conn_fd(conn), true); |
| 604 | |
| 605 | again: |
| 606 | switch (plan->io(conn->fd.fd, &plan->arg)) { |
| 607 | case -1: |
| 608 | ok = false; |
| 609 | break; |
| 610 | /* Incomplete, try again. */ |
| 611 | case 0: |
| 612 | plan->status = IO_POLLING_STARTED; |
| 613 | goto again; |
| 614 | case 1: |
| 615 | ok = true; |
| 616 | /* In case they come back. */ |
| 617 | set_always(conn, IO_OUT, plan->next, plan->next_arg); |
| 618 | break; |
| 619 | default: |
| 620 | /* IO should only return -1, 0 or 1 */ |
| 621 | abort(); |
| 622 | } |
| 623 | |
| 624 | io_fd_block(io_conn_fd(conn), false); |
| 625 | return ok; |
| 626 | } |
| 627 | |
| 628 | void io_set_extended_errors(bool state) |
| 629 | { |