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