diff options
author | Uri Simchoni <urisimchoni@gmail.com> | 2015-06-25 09:46:24 +0300 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2015-07-15 22:41:13 +0200 |
commit | 0c6dc1ecf9ae615b19be412b4d80113296628420 (patch) | |
tree | f24091964606707345ac7e77463d2fd41bb413e0 /lib/async_req | |
parent | 28e1cae4918213ba0cc7903a63d6200e69e5d1c7 (diff) | |
download | samba-0c6dc1ecf9ae615b19be412b4d80113296628420.tar.gz |
async_req: check for errors when monitoring socket for readability
Add an option to wait_for_read_send(), so that the request, upon
calling back, report whether the socket actually contains data
or is in EOF/error state. EOF is signalled via the EPIPE error.
This is useful for clients which do not expect data to arrive but
wait for readability to detect a closed socket (i.e. they do not
intend to actually read the socket when it's readable). Actual data
arrival would indicate a bug in this case, so the check can
be used to print an error message.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11397
Signed-off-by: Uri Simchoni <urisimchoni@gmail.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Diffstat (limited to 'lib/async_req')
-rw-r--r-- | lib/async_req/async_sock.c | 45 | ||||
-rw-r--r-- | lib/async_req/async_sock.h | 4 |
2 files changed, 44 insertions, 5 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index d2cda1572db..bc3780c9199 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -534,6 +534,8 @@ ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct wait_for_read_state { struct tevent_fd *fde; + int fd; + bool check_errors; }; static void wait_for_read_cleanup(struct tevent_req *req, @@ -544,8 +546,8 @@ static void wait_for_read_done(struct tevent_context *ev, void *private_data); struct tevent_req *wait_for_read_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - int fd) + struct tevent_context *ev, int fd, + bool check_errors) { struct tevent_req *req; struct wait_for_read_state *state; @@ -562,6 +564,9 @@ struct tevent_req *wait_for_read_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(state->fde, req)) { return tevent_req_post(req, ev); } + + state->fd = fd; + state->check_errors = check_errors; return req; } @@ -581,10 +586,44 @@ static void wait_for_read_done(struct tevent_context *ev, { struct tevent_req *req = talloc_get_type_abort( private_data, struct tevent_req); + struct wait_for_read_state *state = + tevent_req_data(req, struct wait_for_read_state); + ssize_t nread; + char c; - if (flags & TEVENT_FD_READ) { + if ((flags & TEVENT_FD_READ) == 0) { + return; + } + + if (!state->check_errors) { tevent_req_done(req); + return; } + + nread = recv(state->fd, &c, 1, MSG_PEEK); + + if (nread == 0) { + tevent_req_error(req, EPIPE); + return; + } + + if ((nread == -1) && (errno == EINTR)) { + /* come back later */ + return; + } + + if ((nread == -1) && (errno == ENOTSOCK)) { + /* Ignore this specific error on pipes */ + tevent_req_done(req); + return; + } + + if (nread == -1) { + tevent_req_error(req, errno); + return; + } + + tevent_req_done(req); } bool wait_for_read_recv(struct tevent_req *req, int *perr) diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h index 1b76fabed53..abbf822228d 100644 --- a/lib/async_req/async_sock.h +++ b/lib/async_req/async_sock.h @@ -53,8 +53,8 @@ ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint8_t **pbuf, int *perrno); struct tevent_req *wait_for_read_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - int fd); + struct tevent_context *ev, int fd, + bool check_errors); bool wait_for_read_recv(struct tevent_req *req, int *perr); #endif |