From 2dcdef3890a4037a763cfe50243fffd8a9b5bd5a Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Mon, 13 May 2024 07:36:11 +0000 Subject: [PATCH] Handle expired timers in basic_stream transfer_op Previously, the code only handled expired timers when the buffer was empty. --- .../boost/beast/core/detail/stream_base.hpp | 5 ++++ .../boost/beast/core/impl/basic_stream.hpp | 27 ++++++++++++++----- test/beast/core/basic_stream.cpp | 11 ++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/include/boost/beast/core/detail/stream_base.hpp b/include/boost/beast/core/detail/stream_base.hpp index 8080e949..1c6b2a9a 100644 --- a/include/boost/beast/core/detail/stream_base.hpp +++ b/include/boost/beast/core/detail/stream_base.hpp @@ -132,6 +132,11 @@ struct stream_base return (time_point::max)(); } + static time_point now() noexcept + { + return clock_type::now(); + } + static std::size_t constexpr no_limit = (std::numeric_limits::max)(); }; diff --git a/include/boost/beast/core/impl/basic_stream.hpp b/include/boost/beast/core/impl/basic_stream.hpp index e3cb83f0..21bd9773 100644 --- a/include/boost/beast/core/impl/basic_stream.hpp +++ b/include/boost/beast/core/impl/basic_stream.hpp @@ -313,6 +313,26 @@ public: { BOOST_ASIO_CORO_REENTER(*this) { + // apply the timeout manually, otherwise + // behavior varies across platforms. + if(state().timer.expiry() <= now()) + { + BOOST_ASIO_CORO_YIELD + { + BOOST_ASIO_HANDLER_LOCATION(( + __FILE__, __LINE__, + (isRead ? "basic_stream::async_read_some" + : "basic_stream::async_write_some"))); + + net::dispatch(this->get_immediate_executor(), + net::prepend(std::move(*this), ec, 0)); + } + + impl_->close(); + BOOST_BEAST_ASSIGN_EC(ec, beast::error::timeout); + goto upcall; + } + // handle empty buffers if(detail::buffers_empty(b_)) { @@ -326,13 +346,6 @@ public: async_perform(0, is_read{}); } - // apply the timeout manually, otherwise - // behavior varies across platforms. - if(state().timer.expiry() <= clock_type::now()) - { - impl_->close(); - BOOST_BEAST_ASSIGN_EC(ec, beast::error::timeout); - } goto upcall; } diff --git a/test/beast/core/basic_stream.cpp b/test/beast/core/basic_stream.cpp index 46b3531a..4daf4e5c 100644 --- a/test/beast/core/basic_stream.cpp +++ b/test/beast/core/basic_stream.cpp @@ -656,6 +656,17 @@ public: ioc.restart(); } + { + // non-empty buffer, timeout + test_server srv("*", ep, log); + stream_type s(ioc); + s.socket().connect(srv.local_endpoint()); + s.expires_after(std::chrono::seconds(0)); + s.async_write_some(cb, handler(error::timeout, 0)); + ioc.run(); + ioc.restart(); + } + // abandoned operation { stream_type s(ioc);