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)) { /*