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 <setjmp.h>
33 #include <signal.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sys/types.h>
38 #include <sys/wait.h>
39 #include <time.h>
40 #include <unistd.h>
41
42 #include <android-base/file.h>
43 #include <android-base/stringprintf.h>
44 #include <android-base/test_utils.h>
45 #include <gtest/gtest.h>
46 #include <log/log_read.h>
47
48 #include <atomic>
49 #include <mutex>
50 #include <random>
51 #include <string>
52 #include <thread>
53 #include <vector>
54
55 #include <backtrace/Backtrace.h>
56 #include <backtrace/BacktraceMap.h>
57
58 #include <bionic/malloc.h>
59 #include <tests/utils.h>
60
61 // All DISABLED_ tests are designed to be executed after malloc debug
62 // is enabled. These tests don't run be default, and are executed
63 // by wrappers that will enable various malloc debug features.
64
GetInitialArgs(const char *** args,size_t * num_args)65 extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
66 static const char* initial_args[] = {"--slow_threshold_ms=30000",
67 "--deadline_threshold_ms=1200000"};
68 *args = initial_args;
69 *num_args = 2;
70 return true;
71 }
72
73 class LogReader {
74 public:
LogReader(pid_t pid,log_id log)75 LogReader(pid_t pid, log_id log) {
76 std::call_once(log_start_time_flag_, []() {
77 // Use this to figure out the point at which to start grabbing the log.
78 // This avoids accidentally grabbing data from a previous process with
79 // the same pid.
80 log_start_time_ = {};
81 logger_list* list = android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_NONBLOCK, 1000, 0);
82 if (list == nullptr) {
83 return;
84 }
85 log_msg log_msg;
86 int ret = android_logger_list_read(list, &log_msg);
87 android_logger_list_close(list);
88 if (ret <= 0) {
89 return;
90 }
91 log_start_time_.tv_sec = log_msg.entry.sec;
92 log_start_time_.tv_nsec = log_msg.entry.nsec;
93 });
94
95 std::call_once(jmp_data_key_flag_, []() {
96 pthread_key_create(&jmp_data_key_, [](void* ptr) { free(ptr); });
97 signal(SIGUSR1, [](int) {
98 jmp_buf* jb = reinterpret_cast<jmp_buf*>(pthread_getspecific(jmp_data_key_));
99 if (jb != nullptr) {
100 // The thread reading the log is in a blocking read call that
101 // cannot be interrupted. In order to get out of this read loop,
102 // it's necessary to call longjmp when a SIGUSR1 signal is sent
103 // to the thread.
104 longjmp(*jb, 1);
105 }
106 });
107 });
108
109 reader_.reset(new std::thread([this, pid, log] {
110 tid_.store(gettid(), std::memory_order_release);
111 logger_list* list;
112 while (true) {
113 // Do not use non-blocking mode so that the two threads
114 // are essentially asleep and not consuming any cpu.
115 list = android_logger_list_open(log, 0, 1000, pid);
116 if (list != nullptr) {
117 break;
118 }
119 // Wait for a short time for the log to become available.
120 usleep(1000);
121 }
122
123 jmp_buf* jb = reinterpret_cast<jmp_buf*>(malloc(sizeof(jmp_buf)));
124 if (jb == nullptr) {
125 printf("Failed to allocate memory for jmp_buf\n");
126 return;
127 }
128 pthread_setspecific(jmp_data_key_, jb);
129 if (setjmp(*jb) != 0) {
130 // SIGUSR1 signal hit, we need to terminate the thread.
131 android_logger_list_free(list);
132 return;
133 }
134
135 while (true) {
136 log_msg msg;
137 int actual = android_logger_list_read(list, &msg);
138 if (actual < 0) {
139 if (actual == -EINTR) {
140 // Interrupted retry.
141 continue;
142 }
143 // Unknown error.
144 break;
145 } else if (actual == 0) {
146 // Nothing left to read.
147 break;
148 }
149 // Do not allow SIGUSR1 while processing the log message.
150 // This avoids a deadlock if the thread is being terminated
151 // at this moment.
152 sigset64_t mask_set;
153 sigprocmask64(SIG_SETMASK, nullptr, &mask_set);
154 sigaddset64(&mask_set, SIGUSR1);
155 sigprocmask64(SIG_SETMASK, &mask_set, nullptr);
156
157 {
158 // Lock while appending to the data.
159 std::lock_guard<std::mutex> guard(data_lock_);
160 char* msg_str = msg.msg();
161 // Make sure the message is not empty and recent.
162 if (msg_str != nullptr && (msg.entry.sec > log_start_time_.tv_sec ||
163 (msg.entry.sec == log_start_time_.tv_sec &&
164 msg.entry.nsec > log_start_time_.tv_nsec))) {
165 // Skip the tag part of the message.
166 char* tag = msg_str + 1;
167 msg_str = tag + strlen(tag) + 1;
168 log_data_ += msg_str;
169 if (log_data_.back() != '\n') {
170 log_data_ += '\n';
171 }
172 }
173 }
174
175 // Re-enable SIGUSR1
176 sigprocmask64(SIG_SETMASK, nullptr, &mask_set);
177 sigdelset64(&mask_set, SIGUSR1);
178 sigprocmask64(SIG_SETMASK, &mask_set, nullptr);
179 }
180 android_logger_list_free(list);
181 }));
182 }
183
~LogReader()184 virtual ~LogReader() {
185 tgkill(getpid(), tid_.load(std::memory_order_acquire), SIGUSR1);
186 reader_->join();
187 }
188
GetLog()189 std::string GetLog() {
190 std::lock_guard<std::mutex> guard(data_lock_);
191 return log_data_;
192 }
193
194 private:
195 std::unique_ptr<std::thread> reader_;
196 std::string log_data_;
197 std::mutex data_lock_;
198 std::atomic<pid_t> tid_;
199
200 static std::once_flag jmp_data_key_flag_;
201 static pthread_key_t jmp_data_key_;
202
203 static std::once_flag log_start_time_flag_;
204 static log_time log_start_time_;
205 };
206
207 std::once_flag LogReader::jmp_data_key_flag_;
208 pthread_key_t LogReader::jmp_data_key_;
209
210 std::once_flag LogReader::log_start_time_flag_;
211 log_time LogReader::log_start_time_;
212
213 class MallocDebugSystemTest : public ::testing::Test {
214 protected:
SetUp()215 void SetUp() override {
216 expected_log_strings_.clear();
217 unexpected_log_strings_.clear();
218
219 // All tests expect this message to be present.
220 expected_log_strings_.push_back("malloc debug enabled");
221 }
222
Exec(const char * test_name,const char * debug_options,int expected_exit_code=0)223 void Exec(const char* test_name, const char* debug_options, int expected_exit_code = 0) {
224 std::random_device rd;
225 std::mt19937 generator(rd());
226 std::uniform_int_distribution<> rand_usleep_time(1, 10);
227 std::srand(std::time(nullptr));
228
229 for (size_t i = 0; i < kMaxRetries; i++) {
230 ASSERT_NO_FATAL_FAILURE(InternalExec(test_name, debug_options, expected_exit_code));
231
232 // Due to log messages sometimes getting lost, if a log message
233 // is not present, allow retrying the test.
234 std::string error_msg;
235 bool found_expected = CheckExpectedLogStrings(&error_msg);
236 if (!found_expected) {
237 ASSERT_NE(i, kMaxRetries - 1) << error_msg;
238 // Sleep a random amount of time to attempt to avoid tests syncing
239 // up and sending the log messages at the same time.
240 usleep(1000 * rand_usleep_time(generator));
241 }
242
243 // This doesn't need to be retried since if the log message is
244 // present, that is an immediate fail.
245 ASSERT_NO_FATAL_FAILURE(VerifyUnexpectedLogStrings());
246 if (found_expected) {
247 break;
248 }
249 }
250 }
251
InternalExec(const char * test_name,const char * debug_options,int expected_exit_code)252 void InternalExec(const char* test_name, const char* debug_options, int expected_exit_code) {
253 int fds[2];
254 ASSERT_NE(-1, pipe(fds));
255 ASSERT_NE(-1, fcntl(fds[0], F_SETFL, O_NONBLOCK));
256 if ((pid_ = fork()) == 0) {
257 ASSERT_EQ(0, setenv("LIBC_DEBUG_MALLOC_OPTIONS", debug_options, 1));
258 close(fds[0]);
259 close(STDIN_FILENO);
260 close(STDOUT_FILENO);
261 close(STDERR_FILENO);
262 ASSERT_NE(0, dup2(fds[1], STDOUT_FILENO));
263 ASSERT_NE(0, dup2(fds[1], STDERR_FILENO));
264
265 std::vector<const char*> args;
266 // Get a copy of this argument so it doesn't disappear on us.
267 std::string exec(testing::internal::GetArgvs()[0]);
268 args.push_back(exec.c_str());
269 args.push_back("--gtest_also_run_disabled_tests");
270 std::string filter_arg = std::string("--gtest_filter=") + test_name;
271 args.push_back(filter_arg.c_str());
272 // Need this because some code depends on exit codes from the test run
273 // but the isolation runner does not support that.
274 args.push_back("--no_isolate");
275 args.push_back(nullptr);
276 execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
277 exit(20);
278 }
279 ASSERT_NE(-1, pid_);
280 close(fds[1]);
281
282 // Create threads to read the log output from the forked process as
283 // soon as possible in case there is something flooding the log.
284 log_main_.reset(new LogReader(pid_, LOG_ID_MAIN));
285 log_crash_.reset(new LogReader(pid_, LOG_ID_CRASH));
286
287 output_.clear();
288 std::vector<char> buffer(4096);
289 time_t start_time = time(nullptr);
290 bool read_done = false;
291 while (true) {
292 struct pollfd read_fd = {.fd = fds[0], .events = POLLIN};
293 if (TEMP_FAILURE_RETRY(poll(&read_fd, 1, 1)) > 0) {
294 ssize_t bytes = TEMP_FAILURE_RETRY(read(fds[0], buffer.data(), sizeof(buffer) - 1));
295 if (bytes == -1 && errno == EAGAIN) {
296 continue;
297 }
298 ASSERT_NE(-1, bytes);
299 if (bytes == 0) {
300 read_done = true;
301 break;
302 }
303 output_.append(buffer.data(), bytes);
304 }
305
306 if ((time(nullptr) - start_time) > kReadOutputTimeoutSeconds) {
307 kill(pid_, SIGINT);
308 break;
309 }
310 }
311
312 bool done = false;
313 int status;
314 start_time = time(nullptr);
315 while (true) {
316 int wait_pid = waitpid(pid_, &status, WNOHANG);
317 if (pid_ == wait_pid) {
318 done = true;
319 break;
320 }
321 if ((time(nullptr) - start_time) > kWaitpidTimeoutSeconds) {
322 break;
323 }
324 }
325 if (!done) {
326 kill(pid_, SIGKILL);
327 start_time = time(nullptr);
328 while (true) {
329 int kill_status;
330 int wait_pid = waitpid(pid_, &kill_status, WNOHANG);
331 if (wait_pid == pid_ || (time(nullptr) - start_time) > kWaitpidTimeoutSeconds) {
332 break;
333 }
334 }
335 }
336
337 // Check timeout conditions first.
338 ASSERT_TRUE(read_done) << "Timed out while reading data, output:\n" << output_;
339 ASSERT_TRUE(done) << "Timed out waiting for waitpid, output:\n" << output_;
340
341 ASSERT_FALSE(WIFSIGNALED(status)) << "Failed with signal " << WTERMSIG(status) << "\nOutput:\n"
342 << output_;
343 ASSERT_EQ(expected_exit_code, WEXITSTATUS(status)) << "Output:\n" << output_;
344 }
345
CheckExpectedLogStrings(std::string * error_msg)346 bool CheckExpectedLogStrings(std::string* error_msg) {
347 time_t start = time(nullptr);
348 std::string missing_match;
349 std::string log_str;
350 while (true) {
351 log_str = log_main_->GetLog();
352 missing_match.clear();
353 // Look for the expected strings.
354 for (auto str : expected_log_strings_) {
355 if (log_str.find(str) == std::string::npos) {
356 missing_match = str;
357 break;
358 }
359 }
360 if (missing_match.empty()) {
361 return true;
362 }
363 if ((time(nullptr) - start) > kLogTimeoutSeconds) {
364 break;
365 }
366 }
367
368 *error_msg = android::base::StringPrintf("Didn't find string '%s' in log output:\n%s",
369 missing_match.c_str(), log_str.c_str());
370 return false;
371 }
372
VerifyUnexpectedLogStrings()373 void VerifyUnexpectedLogStrings() {
374 std::string log_str = log_main_->GetLog();
375 for (auto str : unexpected_log_strings_) {
376 ASSERT_TRUE(log_str.find(str) == std::string::npos)
377 << "Unexpectedly found string '" << str << "' in log output:\n"
378 << log_str;
379 }
380 }
381
VerifyLeak(const char * test_prefix)382 void VerifyLeak(const char* test_prefix) {
383 struct FunctionInfo {
384 const char* name;
385 size_t size;
386 };
387 static FunctionInfo functions[] = {
388 {
389 "aligned_alloc",
390 1152,
391 },
392 {
393 "calloc",
394 1123,
395 },
396 {
397 "malloc",
398 1123,
399 },
400 {
401 "memalign",
402 1123,
403 },
404 {
405 "posix_memalign",
406 1123,
407 },
408 {
409 "reallocarray",
410 1123,
411 },
412 {
413 "realloc",
414 1123,
415 },
416 #if !defined(__LP64__)
417 {
418 "pvalloc",
419 4096,
420 },
421 {
422 "valloc",
423 1123,
424 }
425 #endif
426 };
427
428 size_t match_len = expected_log_strings_.size() + 1;
429 expected_log_strings_.resize(match_len);
430 for (size_t i = 0; i < sizeof(functions) / sizeof(FunctionInfo); i++) {
431 SCOPED_TRACE(testing::Message()
432 << functions[i].name << " expected size " << functions[i].size);
433
434 expected_log_strings_[match_len - 1] =
435 android::base::StringPrintf("leaked block of size %zu at", functions[i].size);
436
437 std::string test = std::string("MallocTests.DISABLED_") + test_prefix + functions[i].name;
438 ASSERT_NO_FATAL_FAILURE(Exec(test.c_str(), "verbose backtrace leak_track"));
439 }
440 }
441
442 std::unique_ptr<LogReader> log_main_;
443 std::unique_ptr<LogReader> log_crash_;
444 pid_t pid_;
445 std::string output_;
446 std::vector<std::string> expected_log_strings_;
447 std::vector<std::string> unexpected_log_strings_;
448
449 static constexpr size_t kReadOutputTimeoutSeconds = 180;
450 static constexpr size_t kWaitpidTimeoutSeconds = 10;
451 static constexpr size_t kLogTimeoutSeconds = 5;
452 static constexpr size_t kMaxRetries = 3;
453 };
454
TEST(MallocTests,DISABLED_smoke)455 TEST(MallocTests, DISABLED_smoke) {}
456
TEST_F(MallocDebugSystemTest,smoke)457 TEST_F(MallocDebugSystemTest, smoke) {
458 Exec("MallocTests.DISABLED_smoke", "verbose backtrace");
459 }
460
SetAllocationLimit()461 static void SetAllocationLimit() {
462 // Set to a large value, this is only to enable the limit code and
463 // verify that malloc debug is still called properly.
464 size_t limit = 500 * 1024 * 1024;
465 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
466 }
467
AlignedAlloc()468 static void AlignedAlloc() {
469 void* ptr = aligned_alloc(64, 1152);
470 ASSERT_TRUE(ptr != nullptr);
471 memset(ptr, 0, 1152);
472 }
473
TEST(MallocTests,DISABLED_leak_memory_aligned_alloc)474 TEST(MallocTests, DISABLED_leak_memory_aligned_alloc) {
475 AlignedAlloc();
476 }
477
TEST(MallocTests,DISABLED_leak_memory_limit_aligned_alloc)478 TEST(MallocTests, DISABLED_leak_memory_limit_aligned_alloc) {
479 SetAllocationLimit();
480 AlignedAlloc();
481 }
482
Calloc()483 static void Calloc() {
484 void* ptr = calloc(1, 1123);
485 ASSERT_TRUE(ptr != nullptr);
486 memset(ptr, 1, 1123);
487 }
488
TEST(MallocTests,DISABLED_leak_memory_calloc)489 TEST(MallocTests, DISABLED_leak_memory_calloc) {
490 Calloc();
491 }
492
TEST(MallocTests,DISABLED_leak_memory_limit_calloc)493 TEST(MallocTests, DISABLED_leak_memory_limit_calloc) {
494 SetAllocationLimit();
495 Calloc();
496 }
497
Malloc()498 static void Malloc() {
499 void* ptr = malloc(1123);
500 ASSERT_TRUE(ptr != nullptr);
501 memset(ptr, 0, 1123);
502 }
503
TEST(MallocTests,DISABLED_leak_memory_malloc)504 TEST(MallocTests, DISABLED_leak_memory_malloc) {
505 Malloc();
506 }
507
TEST(MallocTests,DISABLED_leak_memory_limit_malloc)508 TEST(MallocTests, DISABLED_leak_memory_limit_malloc) {
509 SetAllocationLimit();
510 Malloc();
511 }
512
Memalign()513 static void Memalign() {
514 void* ptr = memalign(64, 1123);
515 ASSERT_TRUE(ptr != nullptr);
516 memset(ptr, 0, 1123);
517 }
518
TEST(MallocTests,DISABLED_leak_memory_memalign)519 TEST(MallocTests, DISABLED_leak_memory_memalign) {
520 Memalign();
521 }
522
TEST(MallocTests,DISABLED_leak_memory_limit_memalign)523 TEST(MallocTests, DISABLED_leak_memory_limit_memalign) {
524 SetAllocationLimit();
525 Memalign();
526 }
527
PosixMemalign()528 static void PosixMemalign() {
529 void* ptr;
530 ASSERT_EQ(0, posix_memalign(&ptr, 64, 1123));
531 ASSERT_TRUE(ptr != nullptr);
532 memset(ptr, 0, 1123);
533 }
534
TEST(MallocTests,DISABLED_leak_memory_posix_memalign)535 TEST(MallocTests, DISABLED_leak_memory_posix_memalign) {
536 PosixMemalign();
537 }
538
TEST(MallocTests,DISABLED_leak_memory_limit_posix_memalign)539 TEST(MallocTests, DISABLED_leak_memory_limit_posix_memalign) {
540 SetAllocationLimit();
541 PosixMemalign();
542 }
543
Reallocarray()544 static void Reallocarray() {
545 void* ptr = reallocarray(nullptr, 1, 1123);
546 ASSERT_TRUE(ptr != nullptr);
547 memset(ptr, 0, 1123);
548 }
549
TEST(MallocTests,DISABLED_leak_memory_reallocarray)550 TEST(MallocTests, DISABLED_leak_memory_reallocarray) {
551 Reallocarray();
552 }
553
TEST(MallocTests,DISABLED_leak_memory_limit_reallocarray)554 TEST(MallocTests, DISABLED_leak_memory_limit_reallocarray) {
555 SetAllocationLimit();
556 Reallocarray();
557 }
558
Realloc()559 static void Realloc() {
560 void* ptr = realloc(nullptr, 1123);
561 ASSERT_TRUE(ptr != nullptr);
562 memset(ptr, 0, 1123);
563 }
564
TEST(MallocTests,DISABLED_leak_memory_realloc)565 TEST(MallocTests, DISABLED_leak_memory_realloc) {
566 Realloc();
567 }
568
TEST(MallocTests,DISABLED_leak_memory_limit_realloc)569 TEST(MallocTests, DISABLED_leak_memory_limit_realloc) {
570 SetAllocationLimit();
571 Realloc();
572 }
573
574 #if !defined(__LP64__)
575 extern "C" void* pvalloc(size_t);
576
Pvalloc()577 static void Pvalloc() {
578 void* ptr = pvalloc(1123);
579 ASSERT_TRUE(ptr != nullptr);
580 memset(ptr, 0, 1123);
581 }
582
TEST(MallocTests,DISABLED_leak_memory_pvalloc)583 TEST(MallocTests, DISABLED_leak_memory_pvalloc) {
584 Pvalloc();
585 }
586
TEST(MallocTests,DISABLED_leak_memory_limit_pvalloc)587 TEST(MallocTests, DISABLED_leak_memory_limit_pvalloc) {
588 SetAllocationLimit();
589 Pvalloc();
590 }
591
592 extern "C" void* valloc(size_t);
593
Valloc()594 static void Valloc() {
595 void* ptr = valloc(1123);
596 ASSERT_TRUE(ptr != nullptr);
597 memset(ptr, 0, 1123);
598 }
599
TEST(MallocTests,DISABLED_leak_memory_valloc)600 TEST(MallocTests, DISABLED_leak_memory_valloc) {
601 Valloc();
602 }
603
TEST(MallocTests,DISABLED_leak_memory_limit_valloc)604 TEST(MallocTests, DISABLED_leak_memory_limit_valloc) {
605 SetAllocationLimit();
606 Valloc();
607 }
608 #endif
609
TEST_F(MallocDebugSystemTest,verify_leak)610 TEST_F(MallocDebugSystemTest, verify_leak) {
611 VerifyLeak("leak_memory_");
612 }
613
TEST_F(MallocDebugSystemTest,verify_leak_allocation_limit)614 TEST_F(MallocDebugSystemTest, verify_leak_allocation_limit) {
615 SKIP_WITH_HWASAN;
616 VerifyLeak("leak_memory_limit_");
617 }
618
619 static constexpr int kExpectedExitCode = 30;
620 static constexpr size_t kMaxThreads = sizeof(uint32_t) * 8;
621
TEST(MallocTests,DISABLED_exit_while_threads_allocating)622 TEST(MallocTests, DISABLED_exit_while_threads_allocating) {
623 std::atomic_uint32_t thread_mask = {};
624
625 for (size_t i = 0; i < kMaxThreads; i++) {
626 std::thread malloc_thread([&thread_mask, i] {
627 while (true) {
628 void* ptr = malloc(100);
629 if (ptr == nullptr) {
630 exit(1000);
631 }
632 free(ptr);
633 thread_mask.fetch_or(1U << i);
634 }
635 });
636 malloc_thread.detach();
637 }
638
639 // Wait until each thread has done at least one allocation.
640 while (thread_mask.load() != UINT32_MAX)
641 ;
642 exit(kExpectedExitCode);
643 }
644
645 // Verify that exiting while other threads are doing malloc operations,
646 // that there are no crashes.
TEST_F(MallocDebugSystemTest,exit_while_threads_allocating)647 TEST_F(MallocDebugSystemTest, exit_while_threads_allocating) {
648 for (size_t i = 0; i < 100; i++) {
649 SCOPED_TRACE(::testing::Message() << "Run " << i);
650 ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_exit_while_threads_allocating",
651 "verbose backtrace", kExpectedExitCode));
652
653 std::string log_str = log_crash_->GetLog();
654 ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos)
655 << "Found crash in log.\nLog message: " << log_str << " pid: " << pid_;
656 }
657 }
658
TEST(MallocTests,DISABLED_exit_while_threads_freeing_allocs_with_header)659 TEST(MallocTests, DISABLED_exit_while_threads_freeing_allocs_with_header) {
660 static constexpr size_t kMaxAllocsPerThread = 1000;
661 std::atomic_uint32_t thread_mask = {};
662 std::atomic_bool run;
663
664 std::vector<std::vector<void*>> allocs(kMaxThreads);
665 // Pre-allocate a bunch of memory so that we can try to trigger
666 // the frees after the main thread finishes.
667 for (size_t i = 0; i < kMaxThreads; i++) {
668 for (size_t j = 0; j < kMaxAllocsPerThread; j++) {
669 void* ptr = malloc(8);
670 ASSERT_TRUE(ptr != nullptr);
671 allocs[i].push_back(ptr);
672 }
673 }
674
675 for (size_t i = 0; i < kMaxThreads; i++) {
676 std::thread malloc_thread([&thread_mask, &run, &allocs, i] {
677 thread_mask.fetch_or(1U << i);
678 while (!run)
679 ;
680 for (auto ptr : allocs[i]) {
681 free(ptr);
682 }
683 });
684 malloc_thread.detach();
685 }
686
687 // Wait until all threads are running.
688 while (thread_mask.load() != UINT32_MAX)
689 ;
690 run = true;
691 exit(kExpectedExitCode);
692 }
693
TEST_F(MallocDebugSystemTest,exit_while_threads_freeing_allocs_with_header)694 TEST_F(MallocDebugSystemTest, exit_while_threads_freeing_allocs_with_header) {
695 for (size_t i = 0; i < 50; i++) {
696 SCOPED_TRACE(::testing::Message() << "Run " << i);
697 // Enable guard to force the use of a header.
698 ASSERT_NO_FATAL_FAILURE(
699 Exec("MallocTests.DISABLED_exit_while_threads_freeing_allocs_with_header", "verbose guard",
700 kExpectedExitCode));
701
702 std::string log_str = log_crash_->GetLog();
703 ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos)
704 << "Found crash in log.\nLog message: " << log_str << " pid: " << pid_;
705 }
706 }
707
TEST(MallocTests,DISABLED_write_leak_info)708 TEST(MallocTests, DISABLED_write_leak_info) {
709 TemporaryFile tf;
710 ASSERT_TRUE(tf.fd != -1);
711
712 FILE* fp = fdopen(tf.fd, "w+");
713 if (fp == nullptr) {
714 printf("Unable to create %s\n", tf.path);
715 _exit(1);
716 }
717 tf.release();
718
719 void* ptr = malloc(1000);
720 if (ptr == nullptr) {
721 printf("malloc failed\n");
722 _exit(1);
723 }
724 memset(ptr, 0, 1000);
725
726 android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp, sizeof(fp));
727
728 fclose(fp);
729
730 free(ptr);
731 }
732
TEST_F(MallocDebugSystemTest,write_leak_info_no_header)733 TEST_F(MallocDebugSystemTest, write_leak_info_no_header) {
734 unexpected_log_strings_.push_back(" HAS INVALID TAG ");
735 unexpected_log_strings_.push_back("USED AFTER FREE ");
736 unexpected_log_strings_.push_back("UNKNOWN POINTER ");
737 Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace");
738 }
739
TEST_F(MallocDebugSystemTest,write_leak_info_header)740 TEST_F(MallocDebugSystemTest, write_leak_info_header) {
741 unexpected_log_strings_.push_back(" HAS INVALID TAG ");
742 unexpected_log_strings_.push_back("USED AFTER FREE ");
743 unexpected_log_strings_.push_back("UNKNOWN POINTER ");
744 Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace guard");
745 }
746
TEST(MallocTests,DISABLED_malloc_and_backtrace_deadlock)747 TEST(MallocTests, DISABLED_malloc_and_backtrace_deadlock) {
748 std::atomic_bool running(false);
749 pid_t tid;
750 std::thread thread([&tid, &running] {
751 tid = gettid();
752 running = true;
753 while (running) {
754 void* ptr = malloc(200);
755 if (ptr == nullptr) {
756 return;
757 }
758 free(ptr);
759 }
760 });
761
762 while (!running) {
763 }
764
765 static constexpr size_t kNumUnwinds = 1000;
766 for (size_t i = 0; i < kNumUnwinds; i++) {
767 std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
768 // Only verify that there is at least one frame in the unwind.
769 // This is not a test of the unwinder and clang for arm seems to
770 // produces an increasing number of code that does not have unwind
771 // information.
772 ASSERT_TRUE(backtrace->Unwind(0)) << "Failed on unwind " << i;
773 }
774 running = false;
775 thread.join();
776 }
777
TEST_F(MallocDebugSystemTest,malloc_and_backtrace_deadlock)778 TEST_F(MallocDebugSystemTest, malloc_and_backtrace_deadlock) {
779 // Make sure that malloc debug is enabled and that no timeouts occur during
780 // unwinds.
781 unexpected_log_strings_.push_back("Timed out waiting for ");
782 Exec("MallocTests.DISABLED_malloc_and_backtrace_deadlock", "verbose verify_pointers", 0);
783 }
784