Commit 907063a6 authored by Doron Roberts-Kedes's avatar Doron Roberts-Kedes Committed by Facebook Github Bot

LifoSem Mem Pool: Avoid deadlock during static initialization

Summary:
There is probably a better solution than this, but wanted to publish this diff to point out the issue.

If DeterministicSchedule has been initialize befored the first invocation of LifoSemRawNode<DeterministicAtomic>::pool(), the thread invoking LifoSemRawNode<DeterminsiticAtomic> will
enter __cxa_guard_acquire and the DeterministicAtomic constructor.

Implementations of DeterminsticAtomic may be modified to use
DeterministicSchedule::beforeSharedAccess() in the constructor, which will
deadlock if a second thread invokes LifoSemRawNode<DeterministicAtomic>::pool()
before the first thread is rescheduled. For example, BufferedAtomic requires
shared access during the constructor.

Reviewed By: yfeldblum

Differential Revision: D10478693

fbshipit-source-id: eeb09be9ad0fa06c0bb957fff4d56d120b31c6ee
parent df9c39d7
......@@ -34,6 +34,13 @@ typedef DeterministicSchedule DSched;
LIFOSEM_DECLARE_POOL(DeterministicAtomic, 100000)
class LifoSemTest : public testing::Test {
private:
// pre-init the pool to avoid deadlock when using DeterministicAtomic
using Node = detail::LifoSemRawNode<DeterministicAtomic>;
Node::Pool& pool_{Node::pool()};
};
TEST(LifoSem, basic) {
LifoSem sem;
EXPECT_FALSE(sem.tryWait());
......@@ -75,7 +82,7 @@ TEST(LifoSem, multi) {
<< " post/wait pairs, " << blocks << " blocked";
}
TEST(LifoSem, pingpong) {
TEST_F(LifoSemTest, pingpong) {
DSched sched(DSched::uniform(0));
const int iters = 100;
......@@ -104,7 +111,7 @@ TEST(LifoSem, pingpong) {
}
}
TEST(LifoSem, mutex) {
TEST_F(LifoSemTest, mutex) {
DSched sched(DSched::uniform(0));
const int iters = 100;
......@@ -128,7 +135,7 @@ TEST(LifoSem, mutex) {
}
}
TEST(LifoSem, no_blocking) {
TEST_F(LifoSemTest, no_blocking) {
long seed = folly::randomNumberSeed() % 10000;
LOG(INFO) << "seed=" << seed;
DSched sched(DSched::uniform(seed));
......@@ -157,7 +164,7 @@ TEST(LifoSem, no_blocking) {
}
}
TEST(LifoSem, one_way) {
TEST_F(LifoSemTest, one_way) {
long seed = folly::randomNumberSeed() % 10000;
LOG(INFO) << "seed=" << seed;
DSched sched(DSched::uniformSubset(seed, 1, 6));
......@@ -179,7 +186,7 @@ TEST(LifoSem, one_way) {
}
}
TEST(LifoSem, shutdown_race) {
TEST_F(LifoSemTest, shutdown_race) {
long seed = folly::randomNumberSeed() % 10000;
LOG(INFO) << "seed=" << seed;
......@@ -217,7 +224,7 @@ TEST(LifoSem, shutdown_race) {
EXPECT_TRUE(shutdownLost);
}
TEST(LifoSem, shutdown_multi) {
TEST_F(LifoSemTest, shutdown_multi) {
DSched sched(DSched::uniform(0));
for (int pass = 0; pass < 10; ++pass) {
......@@ -248,7 +255,7 @@ TEST(LifoSem, multi_try_wait_simple) {
ASSERT_EQ(5, n);
}
TEST(LifoSem, multi_try_wait) {
TEST_F(LifoSemTest, multi_try_wait) {
long seed = folly::randomNumberSeed() % 10000;
LOG(INFO) << "seed=" << seed;
DSched sched(DSched::uniform(seed));
......@@ -286,7 +293,7 @@ TEST(LifoSem, multi_try_wait) {
ASSERT_EQ(NPOSTS, consumed);
}
TEST(LifoSem, timeout) {
TEST_F(LifoSemTest, timeout) {
long seed = folly::randomNumberSeed() % 10000;
LOG(INFO) << "seed=" << seed;
DSched sched(DSched::uniform(seed));
......
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