summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/async_req/async_sock.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index 86053d94e8..dfb1a1cdbd 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -386,6 +386,7 @@ struct writev_state {
int count;
size_t total_size;
uint16_t flags;
+ bool err_on_readability;
};
static void writev_trigger(struct tevent_req *req, void *private_data);
@@ -413,10 +414,8 @@ struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
if (state->iov == NULL) {
goto fail;
}
- state->flags = TEVENT_FD_WRITE;
- if (err_on_readability) {
- state->flags |= TEVENT_FD_READ;
- }
+ state->flags = TEVENT_FD_WRITE|TEVENT_FD_READ;
+ state->err_on_readability = err_on_readability;
if (queue == NULL) {
struct tevent_fd *fde;
@@ -462,8 +461,35 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
to_write = 0;
if ((state->flags & TEVENT_FD_READ) && (flags & TEVENT_FD_READ)) {
- tevent_req_error(req, EPIPE);
- return;
+ int ret, value;
+
+ if (state->err_on_readability) {
+ /* Readable and the caller wants an error on read. */
+ tevent_req_error(req, EPIPE);
+ return;
+ }
+
+ /* Might be an error. Check if there are bytes to read */
+ ret = ioctl(state->fd, FIONREAD, &value);
+ /* FIXME - should we also check
+ for ret == 0 and value == 0 here ? */
+ if (ret == -1) {
+ /* There's an error. */
+ tevent_req_error(req, EPIPE);
+ return;
+ }
+ /* A request for TEVENT_FD_READ will succeed from now and
+ forevermore until the bytes are read so if there was
+ an error we'll wait until we do read, then get it in
+ the read callback function. Until then, remove TEVENT_FD_READ
+ from the flags we're waiting for. */
+ state->flags &= ~TEVENT_FD_READ;
+ TEVENT_FD_NOT_READABLE(fde);
+
+ /* If not writable, we're done. */
+ if (!(flags & TEVENT_FD_WRITE)) {
+ return;
+ }
}
for (i=0; i<state->count; i++) {