Skip to content

Commit 3137fb3

Browse files
committed
[lldb/test] Fix data racing issue in TestStackCoreScriptedProcess
This patch should fix an nondeterministic error in TestStackCoreScriptedProcess. In order to test both the multithreading capability and shared library loading in Scripted Processes, the test would create multiple threads that would take the same variable as a reference. The first thread would alter the value and the second thread would monitor the value until it gets altered. This assumed a certain ordering regarding the `std::thread` spawning, however the ordering was not always guaranteed at runtime. To fix that, the test now makes use of a `std::condition_variable` shared between the each thread. On the former, it will notify the other thread when the variable gets initialized or updated and on the latter, it will wait until the variable it receives a new notification. This should fix the data racing issue while preserving the testing coverage. rdar://98678134 Differential Revision: https://reviews.llvm.org/D139484 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 4c9e125 commit 3137fb3

File tree

6 files changed

+30
-29
lines changed

6 files changed

+30
-29
lines changed

lldb/test/API/functionalities/scripted_process/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ override ARCH := $(shell uname -m)
66

77
all: libbaz.dylib a.out
88

9-
libbaz.dylib: baz.c
9+
libbaz.dylib: baz.cpp
1010
$(MAKE) -f $(MAKEFILE_RULES) ARCH=$(ARCH) \
11-
DYLIB_ONLY=YES DYLIB_NAME=baz DYLIB_C_SOURCES=baz.c
11+
DYLIB_ONLY=YES DYLIB_NAME=baz DYLIB_CXX_SOURCES=baz.cpp
1212

1313
include Makefile.rules

lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def tearDown(self):
2323
def create_stack_skinny_corefile(self, file):
2424
self.build()
2525
target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here",
26-
lldb.SBFileSpec("baz.c"))
26+
lldb.SBFileSpec("baz.cpp"))
2727
self.assertTrue(process.IsValid(), "Process is invalid.")
2828
# FIXME: Use SBAPI to save the process corefile.
2929
self.runCmd("process save-core -s stack " + file)
@@ -115,9 +115,9 @@ def cleanup():
115115
self.assertTrue(func, "Invalid function.")
116116

117117
self.assertIn("baz", frame.GetFunctionName())
118-
self.assertEqual(frame.vars.GetSize(), 2)
119-
self.assertEqual(int(frame.vars.GetFirstValueByName('j').GetValue()), 42 * 42)
118+
self.assertGreater(frame.vars.GetSize(), 0)
120119
self.assertEqual(int(frame.vars.GetFirstValueByName('k').GetValue()), 42)
120+
self.assertEqual(int(frame.vars.GetFirstValueByName('j').Dereference().GetValue()), 42 * 42)
121121

122122
corefile_dylib = self.get_module_with_name(corefile_target, 'libbaz.dylib')
123123
self.assertTrue(corefile_dylib, "Dynamic library libbaz.dylib not found.")

lldb/test/API/functionalities/scripted_process/baz.c

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "baz.h"
2+
3+
#include <math.h>
4+
5+
int baz(int &j, std::mutex &mutex, std::condition_variable &cv) {
6+
std::unique_lock<std::mutex> lock(mutex);
7+
cv.wait(lock, [&j] { return j == 42 * 42; });
8+
int k = sqrt(j);
9+
return k; // break here
10+
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
#pragma once
22

3-
int baz(int j);
3+
#include <condition_variable>
4+
#include <mutex>
5+
6+
int baz(int &j, std::mutex &mutex, std::condition_variable &cv);

lldb/test/API/functionalities/scripted_process/main.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
#include <iostream>
2-
#include <mutex>
31
#include <thread>
42

5-
extern "C" {
6-
int baz(int);
7-
}
3+
#include "baz.h"
4+
5+
std::condition_variable cv;
6+
std::mutex mutex;
87

98
int bar(int i) {
109
int j = i * i;
@@ -13,23 +12,20 @@ int bar(int i) {
1312

1413
int foo(int i) { return bar(i); }
1514

16-
void call_and_wait(int &n) {
17-
std::cout << "waiting for computation!" << std::endl;
18-
while (baz(n) != 42)
19-
;
20-
std::cout << "finished computation!" << std::endl;
15+
void compute_pow(int &n) {
16+
std::unique_lock<std::mutex> lock(mutex);
17+
n = foo(n);
18+
lock.unlock();
19+
cv.notify_one(); // waiting thread is notified with n == 42 * 42, cv.wait
20+
// returns
2121
}
2222

23-
void compute_pow(int &n) { n = foo(n); }
23+
void call_and_wait(int &n) { baz(n, mutex, cv); }
2424

2525
int main() {
2626
int n = 42;
27-
std::mutex mutex;
28-
std::unique_lock<std::mutex> lock(mutex);
29-
3027
std::thread thread_1(call_and_wait, std::ref(n));
3128
std::thread thread_2(compute_pow, std::ref(n));
32-
lock.unlock();
3329

3430
thread_1.join();
3531
thread_2.join();

0 commit comments

Comments
 (0)