lib/async_req: let writev_send/recv use TEVENT_FD_ERROR
authorStefan Metzmacher <metze@samba.org>
Thu, 12 Jan 2023 11:54:33 +0000 (12:54 +0100)
committerRalph Boehme <slow@samba.org>
Tue, 24 Oct 2023 09:36:37 +0000 (09:36 +0000)
Unless err_on_readability is true, we use TEVENT_FD_READ only
to detect errors. Now that we have TEVENT_FD_ERROR we should use it.

As a side effect it makes the code much simpler and clearer, as
we can directly map TEVENT_FD_ERROR to EPIPE.

In addition the err_on_readability=true case is now also
clearer, where we just map TEVENT_FD_READ to EPIPE.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/async_req/async_sock.c

index 533b247c13d386a45fc57738aa32fab574c788ce..bdbefd162ac5d8eb872fffe38b4e88562b206d0a 100644 (file)
@@ -278,8 +278,10 @@ struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
        if (tevent_req_nomem(state->iov, req)) {
                return tevent_req_post(req, ev);
        }
-       state->flags = TEVENT_FD_WRITE|TEVENT_FD_READ;
-       state->err_on_readability = err_on_readability;
+       state->flags = TEVENT_FD_WRITE | TEVENT_FD_ERROR;
+       if (err_on_readability) {
+               state->flags |= TEVENT_FD_READ;
+       }
 
        tevent_req_set_cleanup_fn(req, writev_cleanup);
        tevent_req_set_cancel_fn(req, writev_cancel);
@@ -402,36 +404,21 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
        struct writev_state *state =
                tevent_req_data(req, struct writev_state);
 
-       if ((state->flags & TEVENT_FD_READ) && (flags & TEVENT_FD_READ)) {
-               int ret, value;
-
-               if (state->err_on_readability) {
-                       /* Readable and the caller wants an error on read. */
-                       tevent_req_error(req, EPIPE);
-                       return;
-               }
+       if (flags & TEVENT_FD_ERROR) {
+               /*
+                * There's an error, for legacy reasons
+                * we just use EPIPE instead of a more
+                * detailed error using
+                * samba_socket_poll_or_sock_error().
+                */
+               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;
-               }
+       if (flags & TEVENT_FD_READ) {
+               /* Readable and the caller wants an error on read. */
+               tevent_req_error(req, EPIPE);
+               return;
        }
 
        writev_do(req, state);