Skip to content
This repository was archived by the owner on Feb 20, 2023. It is now read-only.

Commit 8a6f19a

Browse files
authored
Add a spin-until-initialized to messenger_test to avoid races. (#1425)
1 parent a84af21 commit 8a6f19a

File tree

1 file changed

+63
-8
lines changed

1 file changed

+63
-8
lines changed

test/messenger/messenger_test.cpp

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ class MessengerTests : public TerrierTest {
7979
return db_main;
8080
}
8181

82-
/** A dirty hack that sleeps for a little while so that sockets can clean up. */
83-
static void DirtySleep() { std::this_thread::sleep_for(std::chrono::seconds(5)); }
82+
/** A dirty hack that sleeps for a little while so that sockets can wake up and clean up. */
83+
static void DirtySleep() { std::this_thread::sleep_for(std::chrono::seconds(2)); }
8484
};
8585

8686
// NOLINTNEXTLINE
@@ -98,14 +98,25 @@ TEST_F(MessengerTests, BasicReplicationTest) {
9898
// done[3] is shared memory (mmap) so that the forked processes can coordinate on when they are done.
9999
// This is done instead of waitpid() because I can't find a way to stop googletest from freaking out on waitpid().
100100
// done[0] : primary, done[1] : replica1, done[2] : replica2.
101+
volatile bool *init = static_cast<volatile bool *>(
102+
mmap(nullptr, 3 * sizeof(bool), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
103+
NOISEPAGE_ASSERT(MAP_FAILED != init, "mmap() failed.");
101104
volatile bool *done = static_cast<volatile bool *>(
102105
mmap(nullptr, 3 * sizeof(bool), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
103106
NOISEPAGE_ASSERT(MAP_FAILED != done, "mmap() failed.");
104107

108+
init[0] = false;
109+
init[1] = false;
110+
init[2] = false;
105111
done[0] = false;
106112
done[1] = false;
107113
done[2] = false;
108114

115+
auto spin_until_init = [init]() {
116+
while (!(init[0] && init[1] && init[2])) {
117+
}
118+
};
119+
109120
auto spin_until_done = [done]() {
110121
while (!(done[0] && done[1] && done[2])) {
111122
}
@@ -115,19 +126,28 @@ TEST_F(MessengerTests, BasicReplicationTest) {
115126
auto primary = BuildDBMain(port_primary, port_messenger_primary, "primary");
116127
primary->GetNetworkLayer()->GetServer()->RunServer();
117128

129+
init[0] = true;
130+
spin_until_init();
131+
DirtySleep();
132+
118133
while (!(done[1] && done[2])) {
119134
}
120135

121136
MESSENGER_LOG_TRACE("Primary done.");
122137
done[0] = true;
123138
spin_until_done();
124139
MESSENGER_LOG_TRACE("Primary exit.");
140+
primary->ForceShutdown();
125141
};
126142

127143
VoidFn replica1_fn = [=]() {
128144
auto replica1 = BuildDBMain(port_replica1, port_messenger_replica1, "replica1");
129145
replica1->GetNetworkLayer()->GetServer()->RunServer();
130146

147+
init[1] = true;
148+
spin_until_init();
149+
DirtySleep();
150+
131151
// Set up a connection to the primary.
132152
auto messenger = replica1->GetMessengerLayer()->GetMessenger();
133153
ConnectionDestination dest_primary = Messenger::GetEndpointIPC("primary", port_messenger_primary);
@@ -168,12 +188,17 @@ TEST_F(MessengerTests, BasicReplicationTest) {
168188
done[1] = true;
169189
spin_until_done();
170190
MESSENGER_LOG_TRACE("Replica 1 exit.");
191+
replica1->ForceShutdown();
171192
};
172193

173194
VoidFn replica2_fn = [=]() {
174195
auto replica2 = BuildDBMain(port_replica2, port_messenger_replica2, "replica2");
175196
replica2->GetNetworkLayer()->GetServer()->RunServer();
176197

198+
init[2] = true;
199+
spin_until_init();
200+
DirtySleep();
201+
177202
// Set up a connection to the primary.
178203
auto messenger = replica2->GetMessengerLayer()->GetMessenger();
179204
ConnectionDestination dest_primary = Messenger::GetEndpointIPC("primary", port_messenger_primary);
@@ -214,6 +239,7 @@ TEST_F(MessengerTests, BasicReplicationTest) {
214239
done[2] = true;
215240
spin_until_done();
216241
MESSENGER_LOG_TRACE("Replica 2 exit.");
242+
replica2->ForceShutdown();
217243
};
218244

219245
std::vector<pid_t> pids = ForkTests({primary_fn, replica1_fn, replica2_fn});
@@ -223,9 +249,14 @@ TEST_F(MessengerTests, BasicReplicationTest) {
223249
}
224250

225251
DirtySleep();
226-
227-
UNUSED_ATTRIBUTE int munmap_retval = munmap(static_cast<void *>(const_cast<bool *>(done)), 3 * sizeof(bool));
228-
NOISEPAGE_ASSERT(-1 != munmap_retval, "munmap() failed.");
252+
{
253+
UNUSED_ATTRIBUTE int munmap_retval = munmap(static_cast<void *>(const_cast<bool *>(init)), 3 * sizeof(bool));
254+
NOISEPAGE_ASSERT(-1 != munmap_retval, "munmap() failed.");
255+
}
256+
{
257+
UNUSED_ATTRIBUTE int munmap_retval = munmap(static_cast<void *>(const_cast<bool *>(done)), 3 * sizeof(bool));
258+
NOISEPAGE_ASSERT(-1 != munmap_retval, "munmap() failed.");
259+
}
229260
}
230261

231262
// NOLINTNEXTLINE
@@ -240,13 +271,23 @@ TEST_F(MessengerTests, BasicListenTest) {
240271

241272
uint16_t port_listen = 8030;
242273

274+
volatile bool *init = static_cast<volatile bool *>(
275+
mmap(nullptr, 2 * sizeof(bool), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
276+
NOISEPAGE_ASSERT(MAP_FAILED != init, "mmap() failed.");
243277
volatile bool *done = static_cast<volatile bool *>(
244278
mmap(nullptr, 2 * sizeof(bool), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
245279
NOISEPAGE_ASSERT(MAP_FAILED != done, "mmap() failed.");
246280

281+
init[0] = false;
282+
init[1] = false;
247283
done[0] = false;
248284
done[1] = false;
249285

286+
auto spin_until_init = [init]() {
287+
while (!(init[0] && init[1])) {
288+
}
289+
};
290+
250291
auto spin_until_done = [done]() {
251292
while (!(done[0] && done[1])) {
252293
}
@@ -269,18 +310,26 @@ TEST_F(MessengerTests, BasicListenTest) {
269310
}
270311
});
271312

313+
init[0] = true;
314+
spin_until_init();
315+
DirtySleep();
316+
272317
while (!done[1]) {
273318
}
274319

275320
MESSENGER_LOG_TRACE("Primary done.");
276321
done[0] = true;
277322
spin_until_done();
278323
MESSENGER_LOG_TRACE("Primary exit.");
324+
primary->ForceShutdown();
279325
};
280326

281327
VoidFn replica1_fn = [=]() {
282328
auto replica1 = BuildDBMain(port_replica1, port_messenger_replica1, "replica1");
283329
replica1->GetNetworkLayer()->GetServer()->RunServer();
330+
init[1] = true;
331+
spin_until_init();
332+
DirtySleep();
284333

285334
// Set up a connection to the primary via the listen endpoint.
286335
auto messenger = replica1->GetMessengerLayer()->GetMessenger();
@@ -316,6 +365,7 @@ TEST_F(MessengerTests, BasicListenTest) {
316365
done[1] = true;
317366
spin_until_done();
318367
MESSENGER_LOG_TRACE("Replica 1 exit.");
368+
replica1->ForceShutdown();
319369
};
320370

321371
std::vector<pid_t> pids = ForkTests({primary_fn, replica1_fn});
@@ -325,9 +375,14 @@ TEST_F(MessengerTests, BasicListenTest) {
325375
}
326376

327377
DirtySleep();
328-
329-
UNUSED_ATTRIBUTE int munmap_retval = munmap(static_cast<void *>(const_cast<bool *>(done)), 2 * sizeof(bool));
330-
NOISEPAGE_ASSERT(-1 != munmap_retval, "munmap() failed.");
378+
{
379+
UNUSED_ATTRIBUTE int munmap_retval = munmap(static_cast<void *>(const_cast<bool *>(init)), 2 * sizeof(bool));
380+
NOISEPAGE_ASSERT(-1 != munmap_retval, "munmap() failed.");
381+
}
382+
{
383+
UNUSED_ATTRIBUTE int munmap_retval = munmap(static_cast<void *>(const_cast<bool *>(done)), 2 * sizeof(bool));
384+
NOISEPAGE_ASSERT(-1 != munmap_retval, "munmap() failed.");
385+
}
331386
}
332387

333388
} // namespace noisepage::messenger

0 commit comments

Comments
 (0)