1f1b6bd40SEvgeniy Stepanov // Regression test for a deadlock in leak detection,
2f1b6bd40SEvgeniy Stepanov // where lsan would call dl_iterate_phdr while holding the allocator lock.
3f1b6bd40SEvgeniy Stepanov // RUN: %clangxx_lsan %s -o %t && %run %t
4f1b6bd40SEvgeniy Stepanov 
5f1b6bd40SEvgeniy Stepanov #include <link.h>
6f1b6bd40SEvgeniy Stepanov #include <mutex>
7f1b6bd40SEvgeniy Stepanov #include <stdlib.h>
8f1b6bd40SEvgeniy Stepanov #include <thread>
9f1b6bd40SEvgeniy Stepanov #include <unistd.h>
10f1b6bd40SEvgeniy Stepanov 
11f1b6bd40SEvgeniy Stepanov std::mutex in, out;
12f1b6bd40SEvgeniy Stepanov 
Callback(struct dl_phdr_info * info,size_t size,void * data)13f1b6bd40SEvgeniy Stepanov int Callback(struct dl_phdr_info *info, size_t size, void *data) {
14f1b6bd40SEvgeniy Stepanov   for (int step = 0; step < 50; ++step) {
15f1b6bd40SEvgeniy Stepanov     void *p[1000];
16f1b6bd40SEvgeniy Stepanov     for (int i = 0; i < 1000; ++i)
17f1b6bd40SEvgeniy Stepanov       p[i] = malloc(10 * i);
18f1b6bd40SEvgeniy Stepanov 
19f1b6bd40SEvgeniy Stepanov     if (step == 0)
20f1b6bd40SEvgeniy Stepanov       in.unlock();
21f1b6bd40SEvgeniy Stepanov 
22f1b6bd40SEvgeniy Stepanov     for (int i = 0; i < 1000; ++i)
23f1b6bd40SEvgeniy Stepanov       free(p[i]);
24f1b6bd40SEvgeniy Stepanov   }
25f1b6bd40SEvgeniy Stepanov   out.unlock();
26f1b6bd40SEvgeniy Stepanov   return 1; // just once
27f1b6bd40SEvgeniy Stepanov }
28f1b6bd40SEvgeniy Stepanov 
Watchdog()29f1b6bd40SEvgeniy Stepanov void Watchdog() {
30f1b6bd40SEvgeniy Stepanov   // This is just a fail-safe to turn a deadlock (in case the bug reappears)
31f1b6bd40SEvgeniy Stepanov   // into a (slow) test failure.
32*c01548c7SDavid Spickett   usleep(40000000);
33f1b6bd40SEvgeniy Stepanov   if (!out.try_lock()) {
34f1b6bd40SEvgeniy Stepanov     write(2, "DEADLOCK\n", 9);
35f1b6bd40SEvgeniy Stepanov     exit(1);
36f1b6bd40SEvgeniy Stepanov   }
37f1b6bd40SEvgeniy Stepanov }
38f1b6bd40SEvgeniy Stepanov 
main()39f1b6bd40SEvgeniy Stepanov int main() {
40f1b6bd40SEvgeniy Stepanov   in.lock();
41f1b6bd40SEvgeniy Stepanov   out.lock();
42f1b6bd40SEvgeniy Stepanov 
43f1b6bd40SEvgeniy Stepanov   std::thread t([] { dl_iterate_phdr(Callback, nullptr); });
44f1b6bd40SEvgeniy Stepanov   t.detach();
45f1b6bd40SEvgeniy Stepanov 
46f1b6bd40SEvgeniy Stepanov   std::thread w(Watchdog);
47f1b6bd40SEvgeniy Stepanov   w.detach();
48f1b6bd40SEvgeniy Stepanov 
49f1b6bd40SEvgeniy Stepanov   // Wait for the malloc thread to preheat, then start leak detection (on exit)
50f1b6bd40SEvgeniy Stepanov   in.lock();
51f1b6bd40SEvgeniy Stepanov   return 0;
52f1b6bd40SEvgeniy Stepanov }
53