X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/7bccebd0f1225014c3525494e4359f9c43f47164..HEAD:/atomicio.c diff --git a/atomicio.c b/atomicio.c index 3939785d..a6b2d127 100644 --- a/atomicio.c +++ b/atomicio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atomicio.c,v 1.19 2006/04/16 07:59:00 djm Exp $ */ +/* $OpenBSD: atomicio.c,v 1.25 2007/06/25 12:02:27 dtucker Exp $ */ /* * Copyright (c) 2006 Damien Miller. All rights reserved. * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. @@ -28,6 +28,20 @@ #include "includes.h" +#include +#include + +#include +#ifdef HAVE_POLL_H +#include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif +#endif +#include +#include + #include "atomicio.h" /* @@ -39,17 +53,20 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) char *s = _s; size_t pos = 0; ssize_t res; + struct pollfd pfd; + pfd.fd = fd; + pfd.events = f == read ? POLLIN : POLLOUT; while (n > pos) { res = (f) (fd, s + pos, n - pos); switch (res) { case -1: -#ifdef EWOULDBLOCK - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) -#else - if (errno == EINTR || errno == EAGAIN) -#endif + if (errno == EINTR) continue; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + (void)poll(&pfd, 1, -1); + continue; + } return 0; case 0: errno = EPIPE; @@ -71,6 +88,7 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, size_t pos = 0, rem; ssize_t res; struct iovec iov_array[IOV_MAX], *iov = iov_array; + struct pollfd pfd; if (iovcnt > IOV_MAX) { errno = EINVAL; @@ -79,12 +97,22 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, /* Make a copy of the iov array because we may modify it below */ memcpy(iov, _iov, iovcnt * sizeof(*_iov)); +#ifndef BROKEN_READV_COMPARISON + pfd.fd = fd; + pfd.events = f == readv ? POLLIN : POLLOUT; +#endif for (; iovcnt > 0 && iov[0].iov_len > 0;) { res = (f) (fd, iov, iovcnt); switch (res) { case -1: - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR) continue; + if (errno == EAGAIN || errno == EWOULDBLOCK) { +#ifndef BROKEN_READV_COMPARISON + (void)poll(&pfd, 1, -1); +#endif + continue; + } return 0; case 0: errno = EPIPE;