diff options
Diffstat (limited to 'atomicio.c')
-rw-r--r-- | atomicio.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/atomicio.c b/atomicio.c index f651a292c..253139e99 100644 --- a/atomicio.c +++ b/atomicio.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: atomicio.c,v 1.23 2006/08/03 03:34:41 deraadt Exp $ */ | 1 | /* $OpenBSD: atomicio.c,v 1.24 2007/06/19 02:04:43 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2006 Damien Miller. All rights reserved. | 3 | * Copyright (c) 2006 Damien Miller. All rights reserved. |
4 | * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. | 4 | * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. |
@@ -30,9 +30,11 @@ | |||
30 | 30 | ||
31 | #include <sys/param.h> | 31 | #include <sys/param.h> |
32 | #include <sys/uio.h> | 32 | #include <sys/uio.h> |
33 | #include <sys/poll.h> | ||
33 | 34 | ||
34 | #include <errno.h> | 35 | #include <errno.h> |
35 | #include <string.h> | 36 | #include <string.h> |
37 | #include <unistd.h> | ||
36 | 38 | ||
37 | #include "atomicio.h" | 39 | #include "atomicio.h" |
38 | 40 | ||
@@ -45,17 +47,24 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) | |||
45 | char *s = _s; | 47 | char *s = _s; |
46 | size_t pos = 0; | 48 | size_t pos = 0; |
47 | ssize_t res; | 49 | ssize_t res; |
50 | struct pollfd pfd; | ||
48 | 51 | ||
52 | pfd.fd = fd; | ||
53 | pfd.events = f == read ? POLLIN : POLLOUT; | ||
49 | while (n > pos) { | 54 | while (n > pos) { |
50 | res = (f) (fd, s + pos, n - pos); | 55 | res = (f) (fd, s + pos, n - pos); |
51 | switch (res) { | 56 | switch (res) { |
52 | case -1: | 57 | case -1: |
53 | #ifdef EWOULDBLOCK | 58 | #ifdef EWOULDBLOCK |
54 | if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) | 59 | if (errno == EINTR || errno == EWOULDBLOCK) |
55 | #else | 60 | #else |
56 | if (errno == EINTR || errno == EAGAIN) | 61 | if (errno == EINTR) |
57 | #endif | 62 | #endif |
58 | continue; | 63 | continue; |
64 | if (errno == EAGAIN) { | ||
65 | (void)poll(&pfd, 1, -1); | ||
66 | continue; | ||
67 | } | ||
59 | return 0; | 68 | return 0; |
60 | case 0: | 69 | case 0: |
61 | errno = EPIPE; | 70 | errno = EPIPE; |
@@ -77,6 +86,7 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, | |||
77 | size_t pos = 0, rem; | 86 | size_t pos = 0, rem; |
78 | ssize_t res; | 87 | ssize_t res; |
79 | struct iovec iov_array[IOV_MAX], *iov = iov_array; | 88 | struct iovec iov_array[IOV_MAX], *iov = iov_array; |
89 | struct pollfd pfd; | ||
80 | 90 | ||
81 | if (iovcnt > IOV_MAX) { | 91 | if (iovcnt > IOV_MAX) { |
82 | errno = EINVAL; | 92 | errno = EINVAL; |
@@ -85,12 +95,18 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, | |||
85 | /* Make a copy of the iov array because we may modify it below */ | 95 | /* Make a copy of the iov array because we may modify it below */ |
86 | memcpy(iov, _iov, iovcnt * sizeof(*_iov)); | 96 | memcpy(iov, _iov, iovcnt * sizeof(*_iov)); |
87 | 97 | ||
98 | pfd.fd = fd; | ||
99 | pfd.events = f == readv ? POLLIN : POLLOUT; | ||
88 | for (; iovcnt > 0 && iov[0].iov_len > 0;) { | 100 | for (; iovcnt > 0 && iov[0].iov_len > 0;) { |
89 | res = (f) (fd, iov, iovcnt); | 101 | res = (f) (fd, iov, iovcnt); |
90 | switch (res) { | 102 | switch (res) { |
91 | case -1: | 103 | case -1: |
92 | if (errno == EINTR || errno == EAGAIN) | 104 | if (errno == EINTR) |
93 | continue; | 105 | continue; |
106 | if (errno == EAGAIN) { | ||
107 | (void)poll(&pfd, 1, -1); | ||
108 | continue; | ||
109 | } | ||
94 | return 0; | 110 | return 0; |
95 | case 0: | 111 | case 0: |
96 | errno = EPIPE; | 112 | errno = EPIPE; |