53 lines · cpp
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 %t4 5#include <link.h>6#include <mutex>7#include <stdlib.h>8#include <thread>9#include <unistd.h>10 11std::mutex in, out;12 13int 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 once27}28 29void 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 39int 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