1// Check that if the list of shared libraries changes between the two race
2// reports, the second report occurring in a new shared library is still
3// symbolized correctly.
4
5// RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so
6// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
7
8#ifdef BUILD_SO
9
10#include <stddef.h>
11#include <unistd.h>
12
13int GLOB_SHARED = 0;
14
15extern "C"
16void *write_from_so(void *unused) {
17  if (unused)
18    sleep(1);
19  GLOB_SHARED++;
20  return NULL;
21}
22
23#else  // BUILD_SO
24
25#include <dlfcn.h>
26#include <pthread.h>
27#include <stdio.h>
28#include <stddef.h>
29#include <unistd.h>
30
31#include <string>
32
33int GLOB = 0;
34
35void *write_glob(void *unused) {
36  if (unused)
37    sleep(1);
38  GLOB++;
39  return NULL;
40}
41
42void race_two_threads(void *(*access_callback)(void *unused)) {
43  pthread_t t1, t2;
44  pthread_create(&t1, NULL, access_callback, (void*)1);
45  pthread_create(&t2, NULL, access_callback, NULL);
46  pthread_join(t1, NULL);
47  pthread_join(t2, NULL);
48}
49
50int main(int argc, char *argv[]) {
51  std::string path = std::string(argv[0]) + std::string("-so.so");
52  race_two_threads(write_glob);
53  // CHECK: write_glob
54  void *lib = dlopen(path.c_str(), RTLD_NOW);
55    if (!lib) {
56    printf("error in dlopen(): %s\n", dlerror());
57    return 1;
58  }
59  void *(*write_from_so)(void *unused);
60  *(void **)&write_from_so = dlsym(lib, "write_from_so");
61  race_two_threads(write_from_so);
62  // CHECK: write_from_so
63  return 0;
64}
65
66#endif  // BUILD_SO
67