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