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