Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different experimental::coro executors cause undefined behavior #1536

Open
terrakuh opened this issue Oct 3, 2024 · 0 comments · May be fixed by #1537
Open

Different experimental::coro executors cause undefined behavior #1536

terrakuh opened this issue Oct 3, 2024 · 0 comments · May be fixed by #1537

Comments

@terrakuh
Copy link

terrakuh commented Oct 3, 2024

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.

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

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();
}
terrakuh added a commit to terrakuh/asio that referenced this issue Oct 3, 2024
Set the cancel member for different coro executors.
Fixes chriskohlhoff#1536
@terrakuh terrakuh linked a pull request Oct 3, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant