1c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko// Check that if the list of shared libraries changes between the two race
2c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko// reports, the second report occurring in a new shared library is still
3c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko// symbolized correctly.
4c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko
55d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so
65d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
75d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
85d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#ifdef BUILD_SO
95d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
105d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#include <stddef.h>
115d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#include <unistd.h>
125d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
135d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesint GLOB_SHARED = 0;
145d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
155d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesextern "C"
165d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesvoid *write_from_so(void *unused) {
175d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (unused)
185d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    sleep(1);
195d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  GLOB_SHARED++;
205d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  return NULL;
215d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines}
225d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
235d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#else  // BUILD_SO
24c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko
25c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko#include <dlfcn.h>
26c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko#include <pthread.h>
27c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko#include <stdio.h>
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <stddef.h>
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <unistd.h>
30c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko
31c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko#include <string>
32c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko
33c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenkoint GLOB = 0;
34c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko
35c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenkovoid *write_glob(void *unused) {
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (unused)
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    sleep(1);
38c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  GLOB++;
39c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  return NULL;
40c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko}
41c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko
428a6cac57625f46e9e9a8977a518e8b92499d612fKostya Serebryanyvoid race_two_threads(void *(*access_callback)(void *unused)) {
43c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  pthread_t t1, t2;
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_create(&t1, NULL, access_callback, (void*)1);
45c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  pthread_create(&t2, NULL, access_callback, NULL);
46c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  pthread_join(t1, NULL);
47c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  pthread_join(t2, NULL);
48c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko}
49c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko
50c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenkoint main(int argc, char *argv[]) {
51c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  std::string path = std::string(argv[0]) + std::string("-so.so");
52c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  race_two_threads(write_glob);
53c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  // CHECK: write_glob
54c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  void *lib = dlopen(path.c_str(), RTLD_NOW);
55c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko    if (!lib) {
56c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko    printf("error in dlopen(): %s\n", dlerror());
57c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko    return 1;
58c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  }
598a6cac57625f46e9e9a8977a518e8b92499d612fKostya Serebryany  void *(*write_from_so)(void *unused);
60c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  *(void **)&write_from_so = dlsym(lib, "write_from_so");
61c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  race_two_threads(write_from_so);
62c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  // CHECK: write_from_so
63c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko  return 0;
64c8feb2fee6dba5cbd1751ded5758910e230d9262Alexander Potapenko}
655d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
665d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#endif  // BUILD_SO
67