From 71e8727bdc085673360f69f6e28afbd6a6adfae7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Jan 2023 10:08:56 +0100 Subject: [PATCH] lib/tsocket: add tstream_bsd_fail_readv_first_error() This gives the caller the option to fail immediately if TEVENT_FD_ERROR appear even with pending bytes in the recv queue. Servers typically want to activate this in order to avoid pointless work, while clients typically want to read pending responses from the recv queue. Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme Reviewed-by: Andrew Bartlett --- lib/tsocket/tsocket.h | 22 ++++++++++++++++++++++ lib/tsocket/tsocket_bsd.c | 25 +++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h index 22eb758bccd..07e10c84a8a 100644 --- a/lib/tsocket/tsocket.h +++ b/lib/tsocket/tsocket.h @@ -844,6 +844,28 @@ int _tdgram_unix_socket(const struct tsocket_address *local, bool tstream_bsd_optimize_readv(struct tstream_context *stream, bool on); +/** + * @brief Request that tstream_readv_send() fails within pending data + * + * By default we allow pending data to be drained from the + * recv queue, before we report EPIPE when reaching EOF. + * + * For server applications it's typically useful to + * fail early in order to avoid useless work, + * as the response can't be transferred to the client anyway. + * + * @param[in] stream The tstream_context of a bsd socket, if this + * not a bsd socket the function does nothing. + * + * @param[in] on The boolean value to turn the early fail on and off. + * + * @return The old boolean value. + * + * @see tstream_readv_send() + */ +bool tstream_bsd_fail_readv_first_error(struct tstream_context *stream, + bool on); + /** * @brief Connect async to a TCP endpoint and create a tstream_context for the * stream based communication. diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c index 2b53d0d79cf..4483b03b19f 100644 --- a/lib/tsocket/tsocket_bsd.c +++ b/lib/tsocket/tsocket_bsd.c @@ -1650,6 +1650,7 @@ struct tstream_bsd { void *event_ptr; struct tevent_fd *fde; bool optimize_readv; + bool fail_readv_first_error; void *readable_private; void (*readable_handler)(void *private_data); @@ -1676,6 +1677,25 @@ bool tstream_bsd_optimize_readv(struct tstream_context *stream, return old; } +bool tstream_bsd_fail_readv_first_error(struct tstream_context *stream, + bool on) +{ + struct tstream_bsd *bsds = + talloc_get_type(_tstream_context_data(stream), + struct tstream_bsd); + bool old; + + if (bsds == NULL) { + /* not a bsd socket */ + return false; + } + + old = bsds->fail_readv_first_error; + bsds->fail_readv_first_error = on; + + return old; +} + static void tstream_bsd_fde_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, @@ -1692,10 +1712,11 @@ static void tstream_bsd_fde_handler(struct tevent_context *ev, * So we have to check TEVENT_FD_READ * as well as bsds->readable_handler * - * We drain remaining data from the - * recv queue if available. + * We only drain remaining data from the + * the recv queue if available and desired. */ if ((flags & TEVENT_FD_READ) && + !bsds->fail_readv_first_error && (bsds->readable_handler != NULL)) { /*