X-Git-Url: https://unix4lyfe.org/gitweb/buftee/blobdiff_plain/82167c1b9ace84dc8f2df347137548e0bb07110c..7ec121b337234db6e694a7140f5732df5e3aa34d:/buftee.c diff --git a/buftee.c b/buftee.c index 77cba3a..feb213b 100644 --- a/buftee.c +++ b/buftee.c @@ -215,31 +215,54 @@ static int xread(const int fd, char* const restrict buf, const int count) { return (int)read_ret; } +static void wait_until_writable(const int fd) { + fd_set write_fds; + FD_ZERO(&write_fds); + FD_SET(fd, &write_fds); + int select_ret = select(fd + 1, NULL, &write_fds, NULL, NULL); + if (select_ret == -1) { + if (errno == EINTR) { + assert(stopping); // that should have been SIGTERM + return; + } + err(1, "select(write fd = %d) failed", fd); + } + if (!FD_ISSET(fd, &write_fds)) + errx(1, "select() did not return writable fd = %d", fd); +} + static int xwrite(const int fd, struct buf* const buf) { ssize_t write_ret; int saved_errno; struct timespec t0; struct timespec t1; - get_mono_time(&t0); - write_ret = write(fd, buf->data, (size_t)buf->len); - saved_errno = errno; - get_mono_time(&t1); - warn_time("write()", &t0, &t1); - - errno = saved_errno; - if (write_ret == -1) - err(1, "write(fd = %d, count = %d) failed", fd, buf->len); - //FIXME: EAGAIN? - if (write_ret == 0) - return 0; - assert(write_ret >= 0); - if (write_ret < buf->len) - err(1, "write(fd = %d, count = %d) stopped short (returned %d)", - fd, buf->len, (int)write_ret); - // FIXME: handle this - assert(write_ret == buf->len); - return (int)write_ret; + for (;;) { + get_mono_time(&t0); + write_ret = write(fd, buf->data, (size_t)buf->len); + saved_errno = errno; + get_mono_time(&t1); + warn_time("write()", &t0, &t1); + + errno = saved_errno; + if (write_ret == -1) { + if (errno == EAGAIN) { + warn("write(fd = %d) got EAGAIN, sleeping and retrying", fd); + wait_until_writable(fd); + continue; + } + err(1, "write(fd = %d, count = %d) failed", fd, buf->len); + } + if (write_ret == 0) + return 0; // EOF + assert(write_ret >= 0); + if (write_ret < buf->len) + err(1, "write(fd = %d, count = %d) stopped short (returned %d)", + fd, buf->len, (int)write_ret); + // FIXME: handle this + assert(write_ret == buf->len); + return (int)write_ret; + } } static void wait_until_readable(const int fd) { @@ -252,7 +275,7 @@ static void wait_until_readable(const int fd) { assert(stopping); // that should have been SIGTERM return; } - err(1, "select() failed"); + err(1, "select(read fd = %d) failed", fd); } if (!FD_ISSET(fd, &read_fds)) errx(1, "select() did not return readable fd = %d", fd);