Add "err_on_readability" to writev_send
authorVolker Lendecke <vl@samba.org>
Sat, 23 May 2009 14:10:54 +0000 (16:10 +0200)
committerVolker Lendecke <vl@samba.org>
Sun, 24 May 2009 11:47:29 +0000 (13:47 +0200)
A socket where the other side has closed only becomes readable. To catch
errors early when sitting in a pure writev, we need to also test for
readability.

lib/async_req/async_sock.c
lib/async_req/async_sock.h
source3/lib/wb_reqtrans.c
source3/libsmb/async_smb.c
source3/rpc_server/srv_pipe_hnd.c

index a3a6d75f3a0b0cad522d5e14d0e9b6c4bdc8164f..d7f31768ef86cd7786e0f05f600a40c17338a9ff 100644 (file)
@@ -327,6 +327,7 @@ struct writev_state {
        struct iovec *iov;
        int count;
        size_t total_size;
+       uint16_t flags;
 };
 
 static void writev_trigger(struct tevent_req *req, void *private_data);
@@ -335,6 +336,7 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
 
 struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
                               struct tevent_queue *queue, int fd,
+                              bool err_on_readability,
                               struct iovec *iov, int count)
 {
        struct tevent_req *req;
@@ -353,11 +355,15 @@ 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;
+       }
 
        if (queue == NULL) {
                struct tevent_fd *fde;
                fde = tevent_add_fd(state->ev, state, state->fd,
-                                   TEVENT_FD_WRITE, writev_handler, req);
+                                   state->flags, writev_handler, req);
                if (tevent_req_nomem(fde, req)) {
                        return tevent_req_post(req, ev);
                }
@@ -378,7 +384,7 @@ static void writev_trigger(struct tevent_req *req, void *private_data)
        struct writev_state *state = tevent_req_data(req, struct writev_state);
        struct tevent_fd *fde;
 
-       fde = tevent_add_fd(state->ev, state, state->fd, TEVENT_FD_WRITE,
+       fde = tevent_add_fd(state->ev, state, state->fd, state->flags,
                            writev_handler, req);
        if (fde == NULL) {
                tevent_req_error(req, ENOMEM);
@@ -397,6 +403,11 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
 
        to_write = 0;
 
+       if (flags & TEVENT_FD_READ) {
+               tevent_req_error(req, EPIPE);
+               return;
+       }
+
        for (i=0; i<state->count; i++) {
                to_write += state->iov[i].iov_len;
        }
index ec859dc0aeed45e7624cc9bebc70faf25f07c22e..a50e93238aa9d24f03f848a51ea7bec9282bcef7 100644 (file)
@@ -41,6 +41,7 @@ int async_connect_recv(struct tevent_req *req, int *perrno);
 
 struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
                               struct tevent_queue *queue, int fd,
+                              bool err_on_readability,
                               struct iovec *iov, int count);
 ssize_t writev_recv(struct tevent_req *req, int *perrno);
 
index df92ecf8b065fde8eb8238bbca08d8acf54cafca..3fdf62a10878bf2c76408ad9bc6cde62866bdc23 100644 (file)
@@ -152,7 +152,7 @@ struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
                count = 2;
        }
 
-       subreq = writev_send(state, ev, queue, fd, state->iov, count);
+       subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -309,7 +309,7 @@ struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
                count = 2;
        }
 
-       subreq = writev_send(state, ev, queue, fd, state->iov, count);
+       subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
index 12bc0a6fb31eae26b12875e35b884aae67413256..6edfe514b806b5c763e7a27d5580597ea80d3985 100644 (file)
@@ -680,10 +680,10 @@ static NTSTATUS cli_smb_req_iov_send(struct tevent_req *req,
                iov[0].iov_base = (void *)buf;
                iov[0].iov_len = talloc_get_size(buf);
                subreq = writev_send(state, state->ev, state->cli->outgoing,
-                                    state->cli->fd, iov, 1);
+                                    state->cli->fd, false, iov, 1);
        } else {
                subreq = writev_send(state, state->ev, state->cli->outgoing,
-                                    state->cli->fd, iov, iov_count);
+                                    state->cli->fd, false, iov, iov_count);
        }
        if (subreq == NULL) {
                return NT_STATUS_NO_MEMORY;
index f2441619ac0cf9d5c9abe8bce8e95c741c9c1346..a17adfb7a0321c3b093dc9229e836252340e7a0f 100644 (file)
@@ -1221,7 +1221,7 @@ struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
                state->iov.iov_len = len;
 
                subreq = writev_send(state, ev, p->write_queue, p->fd,
-                                    &state->iov, 1);
+                                    false, &state->iov, 1);
                if (subreq == NULL) {
                        goto fail;
                }