Skip to content

Commit 287a9cc

Browse files
committed
Make bthread_id_join destroy race test deterministic
1 parent ed9a32f commit 287a9cc

2 files changed

Lines changed: 44 additions & 17 deletions

File tree

‎src/bthread/id.cpp‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030

3131
namespace bthread {
3232

33+
#if defined(UNIT_TEST)
34+
void (*g_bthread_id_join_before_wait_for_test)(void*) = nullptr;
35+
void* g_bthread_id_join_before_wait_arg_for_test = nullptr;
36+
#endif
37+
3338
// This queue reduces the chance to allocate memory for deque
3439
template <typename T, int N>
3540
class SmallQueue {
@@ -549,6 +554,12 @@ int bthread_id_join(bthread_id_t id) {
549554
if (!has_ver) {
550555
break;
551556
}
557+
#if defined(UNIT_TEST)
558+
if (bthread::g_bthread_id_join_before_wait_for_test != nullptr) {
559+
bthread::g_bthread_id_join_before_wait_for_test(
560+
bthread::g_bthread_id_join_before_wait_arg_for_test);
561+
}
562+
#endif
552563
if (bthread::butex_wait(join_butex, expected_ver, nullptr) < 0 &&
553564
errno != EWOULDBLOCK && errno != EINTR) {
554565
return errno;

‎test/bthread_id_unittest.cpp‎

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
namespace bthread {
2929
void id_status(bthread_id_t, std::ostream &);
3030
uint32_t id_value(bthread_id_t id);
31+
extern void (*g_bthread_id_join_before_wait_for_test)(void*);
32+
extern void* g_bthread_id_join_before_wait_arg_for_test;
3133
}
3234

3335
namespace {
@@ -116,33 +118,47 @@ TEST(BthreadIdTest, join_before_destroy) {
116118

117119
struct JoinRaceArgs {
118120
bthread_id_t id;
119-
std::atomic<bool> entered;
121+
std::atomic<bool> join_butex_read;
122+
std::atomic<bool> allow_wait;
120123
};
121124

125+
void pause_join_before_wait(void* arg) {
126+
JoinRaceArgs* args = static_cast<JoinRaceArgs*>(arg);
127+
args->join_butex_read.store(true, std::memory_order_release);
128+
while (!args->allow_wait.load(std::memory_order_acquire)) {
129+
std::this_thread::yield();
130+
}
131+
}
132+
122133
void* join_race_waiter(void* arg) {
123134
JoinRaceArgs* args = static_cast<JoinRaceArgs*>(arg);
124-
args->entered.store(true, std::memory_order_release);
125135
EXPECT_EQ(0, bthread_id_join(args->id));
126136
return nullptr;
127137
}
128138

129139
TEST(BthreadIdTest, join_races_with_destroy) {
130-
for (int i = 0; i < 100; ++i) {
131-
bthread_id_t id;
132-
ASSERT_EQ(0, bthread_id_create(&id, nullptr, nullptr));
133-
JoinRaceArgs args;
134-
args.id = id;
135-
args.entered.store(false, std::memory_order_relaxed);
136-
pthread_t waiter;
137-
ASSERT_EQ(0, pthread_create(&waiter, nullptr, join_race_waiter, &args));
138-
while (!args.entered.load(std::memory_order_acquire)) {
139-
std::this_thread::yield();
140-
}
141-
void* data = nullptr;
142-
ASSERT_EQ(0, bthread_id_trylock(id, &data));
143-
ASSERT_EQ(0, bthread_id_unlock_and_destroy(id));
144-
ASSERT_EQ(0, pthread_join(waiter, nullptr));
140+
bthread_id_t id;
141+
ASSERT_EQ(0, bthread_id_create(&id, nullptr, nullptr));
142+
JoinRaceArgs args;
143+
args.id = id;
144+
args.join_butex_read.store(false, std::memory_order_relaxed);
145+
args.allow_wait.store(false, std::memory_order_relaxed);
146+
bthread::g_bthread_id_join_before_wait_for_test = pause_join_before_wait;
147+
bthread::g_bthread_id_join_before_wait_arg_for_test = &args;
148+
149+
pthread_t waiter;
150+
ASSERT_EQ(0, pthread_create(&waiter, nullptr, join_race_waiter, &args));
151+
while (!args.join_butex_read.load(std::memory_order_acquire)) {
152+
std::this_thread::yield();
145153
}
154+
void* data = nullptr;
155+
ASSERT_EQ(0, bthread_id_trylock(id, &data));
156+
ASSERT_EQ(0, bthread_id_unlock_and_destroy(id));
157+
args.allow_wait.store(true, std::memory_order_release);
158+
ASSERT_EQ(0, pthread_join(waiter, nullptr));
159+
160+
bthread::g_bthread_id_join_before_wait_for_test = nullptr;
161+
bthread::g_bthread_id_join_before_wait_arg_for_test = nullptr;
146162
}
147163

148164
struct OnResetArg {

0 commit comments

Comments
 (0)