1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <poll.h>
32 #include <signal.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <time.h>
39 #include <unistd.h>
40 
41 #include <android-base/file.h>
42 #include <android-base/stringprintf.h>
43 #include <gtest/gtest.h>
44 #include <log/log_read.h>
45 
46 #include <atomic>
47 #include <string>
48 #include <thread>
49 #include <vector>
50 
51 #include <backtrace/Backtrace.h>
52 #include <backtrace/BacktraceMap.h>
53 
54 #include <bionic/malloc.h>
55 
56 // All DISABLED_ tests are designed to be executed after malloc debug
57 // is enabled. These tests don't run be default, and are executed
58 // by wrappers that will enable various malloc debug features.
59 
60 static constexpr time_t kTimeoutSeconds = 10;
61 
GetInitialArgs(const char *** args,size_t * num_args)62 extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
63   static const char* initial_args[] = {"--slow_threshold_ms=30000",
64                                        "--deadline_threshold_ms=1200000"};
65   *args = initial_args;
66   *num_args = 2;
67   return true;
68 }
69 
Exec(const char * test_name,const char * debug_options,pid_t * pid,int exit_code=0,time_t timeout_seconds=kTimeoutSeconds)70 static void Exec(const char* test_name, const char* debug_options, pid_t* pid, int exit_code = 0,
71                  time_t timeout_seconds = kTimeoutSeconds) {
72   int fds[2];
73   ASSERT_NE(-1, pipe(fds));
74   ASSERT_NE(-1, fcntl(fds[0], F_SETFL, O_NONBLOCK));
75   if ((*pid = fork()) == 0) {
76     ASSERT_EQ(0, setenv("LIBC_DEBUG_MALLOC_OPTIONS", debug_options, 1));
77     close(fds[0]);
78     close(STDIN_FILENO);
79     close(STDOUT_FILENO);
80     close(STDERR_FILENO);
81     ASSERT_NE(0, dup2(fds[1], STDOUT_FILENO));
82     ASSERT_NE(0, dup2(fds[1], STDERR_FILENO));
83 
84     std::vector<const char*> args;
85     // Get a copy of this argument so it doesn't disappear on us.
86     std::string exec(testing::internal::GetArgvs()[0]);
87     args.push_back(exec.c_str());
88     args.push_back("--gtest_also_run_disabled_tests");
89     std::string filter_arg = std::string("--gtest_filter=") + test_name;
90     args.push_back(filter_arg.c_str());
91     // Need this because some code depends on exit codes from the test run
92     // but the isolation runner does not support that.
93     args.push_back("--no_isolate");
94     args.push_back(nullptr);
95     execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
96     exit(20);
97   }
98   ASSERT_NE(-1, *pid);
99   close(fds[1]);
100 
101   std::string output;
102   std::vector<char> buffer(4096);
103   time_t start_time = time(nullptr);
104   bool done = false;
105   while (true) {
106     struct pollfd read_fd = {.fd = fds[0], .events = POLLIN};
107     if (TEMP_FAILURE_RETRY(poll(&read_fd, 1, 1)) > 0) {
108       ssize_t bytes = TEMP_FAILURE_RETRY(read(fds[0], buffer.data(), sizeof(buffer) - 1));
109       if (bytes == -1 && errno == EAGAIN) {
110         continue;
111       }
112       ASSERT_NE(-1, bytes);
113       if (bytes == 0) {
114         done = true;
115         break;
116       }
117       output.append(buffer.data(), bytes);
118     }
119 
120     if ((time(nullptr) - start_time) > timeout_seconds) {
121       kill(*pid, SIGINT);
122       break;
123     }
124   }
125   EXPECT_TRUE(done) << "Timed out while reading data, output:\n" << output;
126 
127   done = false;
128   int status;
129   start_time = time(nullptr);
130   while (true) {
131     int wait_pid = waitpid(*pid, &status, WNOHANG);
132     if (*pid == wait_pid) {
133       done = true;
134       break;
135     }
136     if ((time(nullptr) - start_time) > timeout_seconds) {
137       break;
138     }
139   }
140   if (!done) {
141     kill(*pid, SIGKILL);
142     start_time = time(nullptr);
143     while (true) {
144       int kill_status;
145       int wait_pid = waitpid(*pid, &kill_status, WNOHANG);
146       if (wait_pid == *pid || (time(nullptr) - start_time) > timeout_seconds) {
147         break;
148       }
149     }
150   }
151 
152   ASSERT_TRUE(done) << "Timed out waiting for waitpid, output:\n" << output;
153   ASSERT_FALSE(WIFSIGNALED(status))
154       << "Failed with signal " << WTERMSIG(status) << "\nOutput:\n" << output;
155   ASSERT_EQ(exit_code, WEXITSTATUS(status)) << "Output:\n" << output;
156 }
157 
GetLogStr(pid_t pid,std::string * log_str,log_id log=LOG_ID_MAIN)158 static void GetLogStr(pid_t pid, std::string* log_str, log_id log = LOG_ID_MAIN) {
159   log_str->clear();
160 
161   logger_list* list;
162   list = android_logger_list_open(log, ANDROID_LOG_NONBLOCK, 1000, pid);
163   ASSERT_TRUE(list != nullptr);
164 
165   while (true) {
166     log_msg msg;
167     ssize_t actual = android_logger_list_read(list, &msg);
168     if (actual < 0) {
169       if (actual == -EINTR) {
170         // Interrupted retry.
171         continue;
172       } else if (actual == -EAGAIN) {
173         // Non-blocking EOF, finished.
174         break;
175       } else {
176         break;
177       }
178     } else if (actual == 0) {
179       break;
180     }
181     ASSERT_EQ(msg.entry.pid, pid);
182 
183     char* msg_str = msg.msg();
184     if (msg_str != nullptr) {
185       char* tag = msg_str + 1;
186       msg_str = tag + strlen(tag) + 1;
187       *log_str += msg_str;
188       if (log_str->back() != '\n') {
189         *log_str += '\n';
190       }
191     }
192   }
193 
194   android_logger_list_close(list);
195 }
196 
FindStrings(pid_t pid,std::vector<const char * > match_strings,std::vector<const char * > no_match_strings=std::vector<const char * >{},time_t timeout_seconds=kTimeoutSeconds)197 static void FindStrings(pid_t pid, std::vector<const char*> match_strings,
198                         std::vector<const char*> no_match_strings = std::vector<const char*>{},
199                         time_t timeout_seconds = kTimeoutSeconds) {
200   std::string log_str;
201   time_t start = time(nullptr);
202   std::string missing_match;
203   while (true) {
204     GetLogStr(pid, &log_str);
205     missing_match.clear();
206     // Look for the expected strings.
207     for (auto str : match_strings) {
208       if (log_str.find(str) == std::string::npos) {
209         missing_match = str;
210         break;
211       }
212     }
213 
214     // Verify the unexpected strings are not present.
215     for (auto str : no_match_strings) {
216       ASSERT_TRUE(log_str.find(str) == std::string::npos) << "Unexpectedly found '" << str << "' in log output:\n" << log_str;
217     }
218     if (missing_match.empty()) {
219       return;
220     }
221     if ((time(nullptr) - start) > timeout_seconds) {
222       break;
223     }
224   }
225   ASSERT_EQ("", missing_match) << "Didn't find expected log output:\n" << log_str;
226 }
227 
TEST(MallocTests,DISABLED_smoke)228 TEST(MallocTests, DISABLED_smoke) {}
229 
TEST(MallocDebugSystemTest,smoke)230 TEST(MallocDebugSystemTest, smoke) {
231   pid_t pid;
232   ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_smoke", "verbose backtrace", &pid));
233 
234   ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}));
235 }
236 
SetAllocationLimit()237 static void SetAllocationLimit() {
238   // Set to a large value, this is only to enable the limit code and
239   // verify that malloc debug is still called properly.
240   size_t limit = 500 * 1024 * 1024;
241   ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
242 }
243 
AlignedAlloc()244 static void AlignedAlloc() {
245   void* ptr = aligned_alloc(64, 1152);
246   ASSERT_TRUE(ptr != nullptr);
247   memset(ptr, 0, 1152);
248 }
249 
TEST(MallocTests,DISABLED_leak_memory_aligned_alloc)250 TEST(MallocTests, DISABLED_leak_memory_aligned_alloc) {
251   AlignedAlloc();
252 }
253 
TEST(MallocTests,DISABLED_leak_memory_limit_aligned_alloc)254 TEST(MallocTests, DISABLED_leak_memory_limit_aligned_alloc) {
255   SetAllocationLimit();
256   AlignedAlloc();
257 }
258 
Calloc()259 static void Calloc() {
260   void* ptr = calloc(1, 1123);
261   ASSERT_TRUE(ptr != nullptr);
262   memset(ptr, 1, 1123);
263 }
264 
TEST(MallocTests,DISABLED_leak_memory_calloc)265 TEST(MallocTests, DISABLED_leak_memory_calloc) {
266   Calloc();
267 }
268 
TEST(MallocTests,DISABLED_leak_memory_limit_calloc)269 TEST(MallocTests, DISABLED_leak_memory_limit_calloc) {
270   SetAllocationLimit();
271   Calloc();
272 }
273 
Malloc()274 static void Malloc() {
275   void* ptr = malloc(1123);
276   ASSERT_TRUE(ptr != nullptr);
277   memset(ptr, 0, 1123);
278 }
279 
TEST(MallocTests,DISABLED_leak_memory_malloc)280 TEST(MallocTests, DISABLED_leak_memory_malloc) {
281   Malloc();
282 }
283 
TEST(MallocTests,DISABLED_leak_memory_limit_malloc)284 TEST(MallocTests, DISABLED_leak_memory_limit_malloc) {
285   SetAllocationLimit();
286   Malloc();
287 }
288 
Memalign()289 static void Memalign() {
290   void* ptr = memalign(64, 1123);
291   ASSERT_TRUE(ptr != nullptr);
292   memset(ptr, 0, 1123);
293 }
294 
TEST(MallocTests,DISABLED_leak_memory_memalign)295 TEST(MallocTests, DISABLED_leak_memory_memalign) {
296   Memalign();
297 }
298 
TEST(MallocTests,DISABLED_leak_memory_limit_memalign)299 TEST(MallocTests, DISABLED_leak_memory_limit_memalign) {
300   SetAllocationLimit();
301   Memalign();
302 }
303 
PosixMemalign()304 static void PosixMemalign() {
305   void* ptr;
306   ASSERT_EQ(0, posix_memalign(&ptr, 64, 1123));
307   ASSERT_TRUE(ptr != nullptr);
308   memset(ptr, 0, 1123);
309 }
310 
TEST(MallocTests,DISABLED_leak_memory_posix_memalign)311 TEST(MallocTests, DISABLED_leak_memory_posix_memalign) {
312   PosixMemalign();
313 }
314 
TEST(MallocTests,DISABLED_leak_memory_limit_posix_memalign)315 TEST(MallocTests, DISABLED_leak_memory_limit_posix_memalign) {
316   SetAllocationLimit();
317   PosixMemalign();
318 }
319 
Reallocarray()320 static void Reallocarray() {
321   void* ptr = reallocarray(nullptr, 1, 1123);
322   ASSERT_TRUE(ptr != nullptr);
323   memset(ptr, 0, 1123);
324 }
325 
TEST(MallocTests,DISABLED_leak_memory_reallocarray)326 TEST(MallocTests, DISABLED_leak_memory_reallocarray) {
327   Reallocarray();
328 }
329 
TEST(MallocTests,DISABLED_leak_memory_limit_reallocarray)330 TEST(MallocTests, DISABLED_leak_memory_limit_reallocarray) {
331   SetAllocationLimit();
332   Reallocarray();
333 }
334 
Realloc()335 static void Realloc() {
336   void* ptr = realloc(nullptr, 1123);
337   ASSERT_TRUE(ptr != nullptr);
338   memset(ptr, 0, 1123);
339 }
340 
TEST(MallocTests,DISABLED_leak_memory_realloc)341 TEST(MallocTests, DISABLED_leak_memory_realloc) {
342   Realloc();
343 }
344 
TEST(MallocTests,DISABLED_leak_memory_limit_realloc)345 TEST(MallocTests, DISABLED_leak_memory_limit_realloc) {
346   SetAllocationLimit();
347   Realloc();
348 }
349 
350 #if !defined(__LP64__)
351 extern "C" void* pvalloc(size_t);
352 
Pvalloc()353 static void Pvalloc() {
354   void* ptr = pvalloc(1123);
355   ASSERT_TRUE(ptr != nullptr);
356   memset(ptr, 0, 1123);
357 }
358 
TEST(MallocTests,DISABLED_leak_memory_pvalloc)359 TEST(MallocTests, DISABLED_leak_memory_pvalloc) {
360   Pvalloc();
361 }
362 
TEST(MallocTests,DISABLED_leak_memory_limit_pvalloc)363 TEST(MallocTests, DISABLED_leak_memory_limit_pvalloc) {
364   SetAllocationLimit();
365   Pvalloc();
366 }
367 
368 extern "C" void* valloc(size_t);
369 
Valloc()370 static void Valloc() {
371   void* ptr = valloc(1123);
372   ASSERT_TRUE(ptr != nullptr);
373   memset(ptr, 0, 1123);
374 }
375 
TEST(MallocTests,DISABLED_leak_memory_valloc)376 TEST(MallocTests, DISABLED_leak_memory_valloc) {
377   Valloc();
378 }
379 
TEST(MallocTests,DISABLED_leak_memory_limit_valloc)380 TEST(MallocTests, DISABLED_leak_memory_limit_valloc) {
381   SetAllocationLimit();
382   Valloc();
383 }
384 #endif
385 
VerifyLeak(const char * test_prefix)386 static void VerifyLeak(const char* test_prefix) {
387   struct FunctionInfo {
388     const char* name;
389     size_t size;
390   };
391   static FunctionInfo functions[] = {
392     {
393       "aligned_alloc",
394       1152,
395     },
396     {
397       "calloc",
398       1123,
399     },
400     {
401       "malloc",
402       1123,
403     },
404     {
405       "memalign",
406       1123,
407     },
408     {
409       "posix_memalign",
410       1123,
411     },
412     {
413       "reallocarray",
414       1123,
415     },
416     {
417       "realloc",
418       1123,
419     },
420 #if !defined(__LP64__)
421     {
422       "pvalloc",
423       4096,
424     },
425     {
426       "valloc",
427       1123,
428     }
429 #endif
430   };
431 
432   for (size_t i = 0; i < sizeof(functions) / sizeof(FunctionInfo); i++) {
433     pid_t pid;
434     SCOPED_TRACE(testing::Message() << functions[i].name << " expected size " << functions[i].size);
435     std::string test = std::string("MallocTests.DISABLED_") + test_prefix + functions[i].name;
436     ASSERT_NO_FATAL_FAILURE(Exec(test.c_str(), "verbose backtrace leak_track", &pid));
437 
438     std::string expected_leak = android::base::StringPrintf("leaked block of size %zu at", functions[i].size);
439     EXPECT_NO_FATAL_FAILURE(FindStrings(
440         pid, std::vector<const char*>{"malloc debug enabled", expected_leak.c_str()}));
441   }
442 }
443 
TEST(MallocDebugSystemTest,verify_leak)444 TEST(MallocDebugSystemTest, verify_leak) {
445   VerifyLeak("leak_memory_");
446 }
447 
TEST(MallocDebugSystemTest,verify_leak_allocation_limit)448 TEST(MallocDebugSystemTest, verify_leak_allocation_limit) {
449   VerifyLeak("leak_memory_limit_");
450 }
451 
452 static constexpr int kExpectedExitCode = 30;
453 static constexpr size_t kMaxThreads = sizeof(uint32_t) * 8;
454 
TEST(MallocTests,DISABLED_exit_while_threads_allocating)455 TEST(MallocTests, DISABLED_exit_while_threads_allocating) {
456   std::atomic_uint32_t thread_mask = {};
457 
458   for (size_t i = 0; i < kMaxThreads; i++) {
459     std::thread malloc_thread([&thread_mask, i] {
460       while (true) {
461         void* ptr = malloc(100);
462         if (ptr == nullptr) {
463           exit(1000);
464         }
465         free(ptr);
466         thread_mask.fetch_or(1 << i);
467       }
468     });
469     malloc_thread.detach();
470   }
471 
472   // Wait until each thread has done at least one allocation.
473   while (thread_mask.load() != UINT32_MAX)
474     ;
475   exit(kExpectedExitCode);
476 }
477 
478 // Verify that exiting while other threads are doing malloc operations,
479 // that there are no crashes.
TEST(MallocDebugSystemTest,exit_while_threads_allocating)480 TEST(MallocDebugSystemTest, exit_while_threads_allocating) {
481   for (size_t i = 0; i < 100; i++) {
482     SCOPED_TRACE(::testing::Message() << "Run " << i);
483     pid_t pid;
484     ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_exit_while_threads_allocating",
485                                  "verbose backtrace", &pid, kExpectedExitCode));
486 
487     ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}));
488 
489     std::string log_str;
490     GetLogStr(pid, &log_str, LOG_ID_CRASH);
491     ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos)
492         << "Found crash in log.\nLog message: " << log_str;
493   }
494 }
495 
TEST(MallocTests,DISABLED_exit_while_threads_freeing_allocs_with_header)496 TEST(MallocTests, DISABLED_exit_while_threads_freeing_allocs_with_header) {
497   static constexpr size_t kMaxAllocsPerThread = 1000;
498   std::atomic_uint32_t thread_mask = {};
499   std::atomic_bool run;
500 
501   std::vector<std::vector<void*>> allocs(kMaxThreads);
502   // Pre-allocate a bunch of memory so that we can try to trigger
503   // the frees after the main thread finishes.
504   for (size_t i = 0; i < kMaxThreads; i++) {
505     for (size_t j = 0; j < kMaxAllocsPerThread; j++) {
506       void* ptr = malloc(8);
507       ASSERT_TRUE(ptr != nullptr);
508       allocs[i].push_back(ptr);
509     }
510   }
511 
512   for (size_t i = 0; i < kMaxThreads; i++) {
513     std::thread malloc_thread([&thread_mask, &run, &allocs, i] {
514       thread_mask.fetch_or(1 << i);
515       while (!run)
516         ;
517       for (auto ptr : allocs[i]) {
518         free(ptr);
519       }
520     });
521     malloc_thread.detach();
522   }
523 
524   // Wait until all threads are running.
525   while (thread_mask.load() != UINT32_MAX)
526     ;
527   run = true;
528   exit(kExpectedExitCode);
529 }
530 
TEST(MallocDebugSystemTest,exit_while_threads_freeing_allocs_with_header)531 TEST(MallocDebugSystemTest, exit_while_threads_freeing_allocs_with_header) {
532   for (size_t i = 0; i < 50; i++) {
533     SCOPED_TRACE(::testing::Message() << "Run " << i);
534     pid_t pid;
535     // Enable guard to force the use of a header.
536     ASSERT_NO_FATAL_FAILURE(
537         Exec("MallocTests.DISABLED_exit_while_threads_freeing_allocs_with_header", "verbose guard",
538              &pid, kExpectedExitCode));
539 
540     ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}));
541 
542     std::string log_str;
543     GetLogStr(pid, &log_str, LOG_ID_CRASH);
544     ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos)
545         << "Found crash in log.\nLog message: " << log_str;
546   }
547 }
548 
TEST(MallocTests,DISABLED_write_leak_info)549 TEST(MallocTests, DISABLED_write_leak_info) {
550   TemporaryFile tf;
551   ASSERT_TRUE(tf.fd != -1);
552 
553   FILE* fp = fdopen(tf.fd, "w+");
554   if (fp == nullptr) {
555     printf("Unable to create %s\n", tf.path);
556     _exit(1);
557   }
558   tf.release();
559 
560   void* ptr = malloc(1000);
561   if (ptr == nullptr) {
562     printf("malloc failed\n");
563     _exit(1);
564   }
565   memset(ptr, 0, 1000);
566 
567   android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp, sizeof(fp));
568 
569   fclose(fp);
570 
571   free(ptr);
572 }
573 
TEST(MallocDebugSystemTest,write_leak_info_no_header)574 TEST(MallocDebugSystemTest, write_leak_info_no_header) {
575   pid_t pid;
576   ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace", &pid, 0));
577 
578   ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"},
579 
580                           std::vector<const char*>{" HAS INVALID TAG ", "USED AFTER FREE ", "UNKNOWN POINTER "}));
581 }
582 
TEST(MallocDebugSystemTest,write_leak_info_header)583 TEST(MallocDebugSystemTest, write_leak_info_header) {
584   pid_t pid;
585   ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace guard", &pid, 0));
586 
587   ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"},
588                           std::vector<const char*>{" HAS INVALID TAG ", "USED AFTER FREE ", "UNKNOWN POINTER "}));
589 }
590 
TEST(MallocTests,DISABLED_malloc_and_backtrace_deadlock)591 TEST(MallocTests, DISABLED_malloc_and_backtrace_deadlock) {
592   std::atomic_bool running(false);
593   pid_t tid;
594   std::thread thread([&tid, &running] {
595     tid = gettid();
596     running = true;
597     while (running) {
598       void* ptr = malloc(200);
599       if (ptr == nullptr) {
600         return;
601       }
602       free(ptr);
603     }
604   });
605 
606   while (!running) {
607   }
608 
609   static constexpr size_t kNumUnwinds = 1000;
610   for (size_t i = 0; i < kNumUnwinds; i++) {
611     std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
612     // Only verify that there is at least one frame in the unwind.
613     // This is not a test of the unwinder and clang for arm seems to
614     // produces an increasing number of code that does not have unwind
615     // information.
616     ASSERT_TRUE(backtrace->Unwind(0)) << "Failed on unwind " << i;
617   }
618   running = false;
619   thread.join();
620 }
621 
TEST(MallocDebugSystemTest,malloc_and_backtrace_deadlock)622 TEST(MallocDebugSystemTest, malloc_and_backtrace_deadlock) {
623   pid_t pid;
624   ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_malloc_and_backtrace_deadlock",
625                                "verbose verify_pointers", &pid, 0, 180));
626 
627   // Make sure that malloc debug is enabled and that no timeouts occur during
628   // unwinds.
629   ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"},
630                                       std::vector<const char*>{"Timed out waiting for "}));
631 }
632