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