Commit d62c61c5 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Possible deadlock with InlineTask and Mutex

Summary: This demonstrates a deadlock that's possible when using InlineTask.

Reviewed By: lbrandy

Differential Revision: D9883432

fbshipit-source-id: 45bb14181f6cfec41851315c0369232a30ba13d9
parent 6c70bf25
......@@ -27,6 +27,7 @@
#include <folly/experimental/coro/Mutex.h>
#include <folly/experimental/coro/Promise.h>
#include <folly/experimental/coro/Task.h>
#include <folly/experimental/coro/detail/InlineTask.h>
#include <folly/portability/GTest.h>
#include <mutex>
......@@ -157,4 +158,37 @@ TEST(Mutex, ThreadSafety) {
CHECK_EQ(30'000, value);
}
TEST(Mutex, InlineTaskDeadlock) {
coro::Mutex coroMutex;
std::timed_mutex stdMutex;
std::thread thread1([&] {
coro::blockingWait(
[](auto& coroMutex, auto& stdMutex) -> coro::detail::InlineTask<void> {
co_await coroMutex.co_lock();
std::this_thread::sleep_for(std::chrono::milliseconds{200});
stdMutex.lock();
// At this point the other coroutine is suspended waiting on
// coroMutex.co_lock(). coroMutex.unlock() will unlock the mutex and
// run the other coroutine *inline*. That coroutine will
// try to acquire stdMutex resulting in a deadlock.
coroMutex.unlock();
stdMutex.unlock();
}(coroMutex, stdMutex));
});
std::thread thread2([&] {
coro::blockingWait(
[](auto& coroMutex, auto& stdMutex) -> coro::detail::InlineTask<void> {
std::this_thread::sleep_for(std::chrono::milliseconds{100});
co_await coroMutex.co_lock();
EXPECT_FALSE(stdMutex.try_lock_for(std::chrono::milliseconds{500}));
coroMutex.unlock();
}(coroMutex, stdMutex));
});
thread1.join();
thread2.join();
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment