beast support per-op cancellation

- websocket supports cancellation.
 - Iterating test for ws cancellation.
 - Only terminal cancellation is forwarded by default.
 - basic_stream supports cancellation.
 - supported cancellation is documented.
 - http cancellation additions.
 - Added cancellation_slot tests to http, utils and saved_handler.
 - Added post to write.cpp, to avoid SIGSEV in test.
 - Refresher describes cancellation in more detail.
This commit is contained in:
Klemens
2022-10-27 22:56:19 +08:00
committed by Klemens Morgenstern
parent 0bf3d971a0
commit 3ebff60b1a
35 changed files with 1216 additions and 29 deletions
@@ -266,6 +266,9 @@ public:
// read and respond to an upgrade request
//
// Cancellation: the async_accept cancellation can be terminal
// because it will just interrupt the reading of the header.
//
template<class NextLayer, bool deflateSupported>
template<class Handler, class Decorator>
class stream<NextLayer, deflateSupported>::accept_op
+18 -4
View File
@@ -90,9 +90,15 @@ public:
BOOST_ASIO_HANDLER_LOCATION((
__FILE__, __LINE__,
"websocket::async_close"));
impl.op_close.emplace(std::move(*this));
this->set_allowed_cancellation(net::cancellation_type::all);
impl.op_close.emplace(std::move(*this),
net::cancellation_type::all);
}
// cancel fired before we could do anything.
if (ec == net::error::operation_aborted)
return this->complete(cont, ec);
this->set_allowed_cancellation(net::cancellation_type::terminal);
impl.wr_block.lock(this);
BOOST_ASIO_CORO_YIELD
{
@@ -143,9 +149,17 @@ public:
BOOST_ASIO_HANDLER_LOCATION((
__FILE__, __LINE__,
"websocket::async_close"));
// terminal only, that's the default
impl.op_r_close.emplace(std::move(*this));
}
if (ec == net::error::operation_aborted)
{
// if a cancellation fires here, we do a dirty shutdown
impl.change_status(status::closed);
close_socket(get_lowest_layer(impl.stream()));
return this->complete(cont, ec);
}
impl.rd_block.lock(this);
BOOST_ASIO_CORO_YIELD
{
@@ -185,7 +199,7 @@ public:
beast::detail::bind_continuation(std::move(*this)));
}
impl.rd_buf.commit(bytes_transferred);
if(impl.check_stop_now(ec))
if(impl.check_stop_now(ec)) //< this catches cancellation
goto upcall;
}
if(detail::is_control(impl.rd_fh.op))
+5 -2
View File
@@ -86,9 +86,12 @@ public:
BOOST_ASIO_HANDLER_LOCATION((
__FILE__, __LINE__,
"websocket::async_ping"));
impl.op_ping.emplace(std::move(*this));
this->set_allowed_cancellation(net::cancellation_type::all);
impl.op_ping.emplace(std::move(*this), net::cancellation_type::all);
}
if (ec)
return this->complete(cont, ec);
this->set_allowed_cancellation(net::cancellation_type::terminal);
impl.wr_block.lock(this);
BOOST_ASIO_CORO_YIELD
{
+13 -1
View File
@@ -107,8 +107,14 @@ public:
__FILE__, __LINE__,
"websocket::async_read_some"));
impl.op_r_rd.emplace(std::move(*this));
this->set_allowed_cancellation(net::cancellation_type::all);
impl.op_r_rd.emplace(std::move(*this), net::cancellation_type::all);
}
if (ec)
return this->complete(cont, ec, bytes_written_);
this->set_allowed_cancellation(net::cancellation_type::terminal);
impl.rd_block.lock(this);
BOOST_ASIO_CORO_YIELD
{
@@ -275,6 +281,9 @@ public:
impl.op_rd.emplace(std::move(*this));
}
if (ec)
return this->complete(cont, ec, bytes_written_);
impl.wr_block.lock(this);
BOOST_ASIO_CORO_YIELD
{
@@ -629,6 +638,9 @@ public:
impl.op_rd.emplace(std::move(*this));
}
if (ec)
return this->complete(cont, ec, bytes_written_);
impl.wr_block.lock(this);
BOOST_ASIO_CORO_YIELD
{
@@ -66,6 +66,8 @@ struct ssl_shutdown_op
{
BOOST_ASIO_CORO_REENTER(*this)
{
self.reset_cancellation_state(net::enable_total_cancellation());
BOOST_ASIO_CORO_YIELD
s_.async_shutdown(std::move(self));
ec_ = ec;
@@ -59,6 +59,7 @@ public:
, nb_(false)
{
(*this)({}, 0, false);
this->set_allowed_cancellation(net::cancellation_type::all);
}
void
+7 -2
View File
@@ -181,9 +181,14 @@ operator()(
"websocket::async_write" :
"websocket::async_write_some"
));
impl.op_wr.emplace(std::move(*this));
this->set_allowed_cancellation(net::cancellation_type::all);
impl.op_wr.emplace(std::move(*this),
net::cancellation_type::all);
}
if (ec)
return this->complete(cont, ec, bytes_transferred_);
this->set_allowed_cancellation(net::cancellation_type::terminal);
impl.wr_block.lock(this);
BOOST_ASIO_CORO_YIELD
{
+12
View File
@@ -68,6 +68,18 @@ teardown(
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::partial
@li @c net::cancellation_type::total
if they are also supported by the socket's @c async_teardown
and @c async_shutdown operation.
*/
template<class AsyncStream, class TeardownHandler>
void
+136
View File
@@ -1602,6 +1602,20 @@ public:
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
@note `terminal` cancellation will may close the underlying socket.
@see
@li <a href="https://tools.ietf.org/html/rfc6455#section-7.1.2">Websocket Closing Handshake (RFC6455)</a>
*/
@@ -1706,6 +1720,21 @@ public:
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<
BOOST_BEAST_ASYNC_TPARAM1 WriteHandler =
@@ -1814,6 +1843,21 @@ public:
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<
BOOST_BEAST_ASYNC_TPARAM1 WriteHandler =
@@ -1975,6 +2019,21 @@ public:
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<
class DynamicBuffer,
@@ -2154,6 +2213,21 @@ public:
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<
class DynamicBuffer,
@@ -2258,6 +2332,21 @@ public:
from the beginning.
@param ec Set to indicate what error occurred, if any.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<class MutableBufferSequence>
std::size_t
@@ -2329,6 +2418,22 @@ public:
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<
class MutableBufferSequence,
@@ -2452,6 +2557,21 @@ public:
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<
class ConstBufferSequence,
@@ -2490,6 +2610,7 @@ public:
@return The number of bytes sent from the buffers.
@throws system_error Thrown on failure.
*/
template<class ConstBufferSequence>
std::size_t
@@ -2575,6 +2696,21 @@ public:
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::total
`total` cancellation succeeds if the operation is suspended due to ongoing
control operations such as a ping/pong.
`terminal` cancellation succeeds when supported by the underlying stream.
`terminal` cancellation leaves the stream in an undefined state,
so that only closing it is guaranteed to succeed.
*/
template<
class ConstBufferSequence,
@@ -163,6 +163,17 @@ teardown(
this function. Invocation of the handler will be performed in a
manner equivalent to using `net::post`.
@par Per-Operation Cancellation
This asynchronous operation supports cancellation for the following
net::cancellation_type values:
@li @c net::cancellation_type::terminal
@li @c net::cancellation_type::partial
@li @c net::cancellation_type::total
if they are also supported by the socket's @c async_wait operation.
*/
template<
class Protocol, class Executor,