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

Cancellation deadlock #221

Open
apollo1321 opened this issue Jan 23, 2024 · 0 comments
Open

Cancellation deadlock #221

apollo1321 opened this issue Jan 23, 2024 · 0 comments

Comments

@apollo1321
Copy link

The following code reproduces cancellation deadlock. I understand the essence of the problem, if anyone is interested, I would be happy to discuss it. Also, I have studied the facebook/folly code, there is no such problem, since in-place executors are not allowed for stackless coroutines. It seems to me that this problem might be quite general. I did not find any mention of it in the std::execution proposal and in the P2175R0 paper, and do not fully understand how it deals with it.

#include "doctest/doctest.h"

#include <cppcoro/cancellation_registration.hpp>
#include <cppcoro/cancellation_source.hpp>
#include <cppcoro/single_consumer_event.hpp>
#include <cppcoro/static_thread_pool.hpp>
#include <cppcoro/sync_wait.hpp>
#include <cppcoro/task.hpp>
#include <cppcoro/when_all.hpp>

#include <chrono>
#include <thread>

TEST_SUITE_BEGIN("cancellation with events tests");

TEST_CASE("check deadlock freedom for events in cancellation callbacks")
{
	cppcoro::static_thread_pool threadPool(3);

	for (int i = 0; i < 20000; ++i)
	{
		cppcoro::single_consumer_event event1;
		cppcoro::single_consumer_event event2;

		cppcoro::cancellation_source source1;
		cppcoro::cancellation_source source2;

		auto coro1 = [&]() -> cppcoro::task<void> {
			auto guard =
				cppcoro::cancellation_registration(source1.token(), [&]() { event2.set(); });
			co_await event1;
		};

		auto coro2 = [&]() -> cppcoro::task<void> {
			auto guard =
				cppcoro::cancellation_registration(source2.token(), [&]() { event1.set(); });
			co_await event2;
		};

		auto cancelCoro1 = [&]() -> cppcoro::task<void> {
			co_await threadPool.schedule();
			source1.request_cancellation();
		};

		auto cancelCoro2 = [&]() -> cppcoro::task<void> {
			co_await threadPool.schedule();
			source2.request_cancellation();
		};

		auto fallbackCoro = [&]() -> cppcoro::task<void> {
			co_await threadPool.schedule();
			std::this_thread::sleep_for(std::chrono::microseconds(10));
			event1.set();
			event2.set();
		};

		cppcoro::sync_wait(
			cppcoro::when_all(coro1(), coro2(), cancelCoro1(), cancelCoro2(), fallbackCoro()));
	}
}

TEST_SUITE_END();
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

No branches or pull requests

1 participant