aboutsummaryrefslogtreecommitdiff
path: root/test/tsan/dl_iterate_phdr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/tsan/dl_iterate_phdr.cc')
-rw-r--r--test/tsan/dl_iterate_phdr.cc56
1 files changed, 56 insertions, 0 deletions
diff --git a/test/tsan/dl_iterate_phdr.cc b/test/tsan/dl_iterate_phdr.cc
new file mode 100644
index 000000000000..b230a920ac4f
--- /dev/null
+++ b/test/tsan/dl_iterate_phdr.cc
@@ -0,0 +1,56 @@
+// RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+// If we mention TSAN_OPTIONS, the test won't run from test_output.sh script.
+
+#ifdef BUILD_SO
+
+#include "test.h"
+
+int exported_var = 0;
+
+#else // BUILD_SO
+
+#include "test.h"
+#include <dlfcn.h>
+#include <link.h>
+#include <string.h>
+#include <string>
+
+static int callback(struct dl_phdr_info *info, size_t size, void *data) {
+ if (info->dlpi_name[0] == '\0')
+ info->dlpi_name = "/proc/self/exe";
+ return !strcmp(info->dlpi_name, "non existent module");
+}
+
+void *thread(void *unused) {
+ for (int i = 0; i < 1000; i++) {
+ barrier_wait(&barrier);
+ dl_iterate_phdr(callback, 0);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ barrier_init(&barrier, 2);
+ std::string path = std::string(argv[0]) + std::string("-so.so");
+ pthread_t th;
+ pthread_create(&th, 0, thread, 0);
+ for (int i = 0; i < 1000; i++) {
+ barrier_wait(&barrier);
+ void *lib = dlopen(path.c_str(), RTLD_NOW);
+ if (!lib) {
+ printf("error in dlopen: %s\n", dlerror());
+ return 1;
+ }
+ dlclose(lib);
+ }
+ pthread_join(th, 0);
+ printf("DONE\n");
+ return 0;
+}
+
+#endif // BUILD_SO
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+// CHECK: DONE