Open terrakuh opened 1 month ago
The implementation of experimental::coro does not properly set the cancel on suspension when the suspended coro and the new one have different executors. The result is undefined behavior.
experimental::coro
cancel
The problem I'm referring occurs in the else branch. Note the coro_.coro_->cancel is not set: https://github.com/chriskohlhoff/asio/blob/master/asio/include/asio/experimental/impl/coro.hpp#L983-L1032
else
coro_.coro_->cancel
The problem can be reproduced with:
#include <boost/asio.hpp> #include <boost/asio/experimental/coro.hpp> #include <boost/asio/experimental/use_coro.hpp> using namespace boost::asio; using namespace boost::asio::experimental; using namespace std::chrono_literals; int main() { io_service service{}; static_thread_pool pool{ 1 }; const auto my_coro = [&](any_io_executor, auto dur) -> coro<int> { steady_timer timer{ service }; timer.expires_after(dur); co_await timer.async_wait(use_coro); }; co_spawn( service, [&] -> awaitable<void> { auto gen = my_coro(pool.get_executor(), 2s); co_await gen.async_resume(use_awaitable); }, detached); cancellation_signal signal{}; co_spawn( service, [&] -> awaitable<void> { auto gen = my_coro(pool.get_executor(), 5s); co_await gen.async_resume(use_awaitable); }, bind_cancellation_slot(signal.slot(), detached)); signal_set set{ service, SIGINT }; set.async_wait([&](auto, int) { signal.emit(cancellation_type::all); }); service.run(); }
The implementation of
experimental::coro
does not properly set thecancel
on suspension when the suspended coro and the new one have different executors. The result is undefined behavior.The problem I'm referring occurs in the
else
branch. Note thecoro_.coro_->cancel
is not set: https://github.com/chriskohlhoff/asio/blob/master/asio/include/asio/experimental/impl/coro.hpp#L983-L1032The problem can be reproduced with: