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