1 /* 2 * Copyright 2017, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <debuggerd/client.h> 18 19 #include <fcntl.h> 20 #include <stdio.h> 21 #include <unistd.h> 22 23 #include <chrono> 24 #include <thread> 25 #include <vector> 26 27 #include <gtest/gtest.h> 28 29 #include <android-base/file.h> 30 #include <android-base/properties.h> 31 #include <android-base/stringprintf.h> 32 #include <android-base/strings.h> 33 #include <android-base/unique_fd.h> 34 35 #include "util.h" 36 37 using namespace std::chrono_literals; 38 using android::base::unique_fd; 39 40 static int getThreadCount() { 41 int threadCount = 1024; 42 std::vector<std::string> characteristics = 43 android::base::Split(android::base::GetProperty("ro.build.characteristics", ""), ","); 44 if (std::find(characteristics.begin(), characteristics.end(), "embedded") 45 != characteristics.end()) { 46 // 128 is the realistic number for iot devices. 47 threadCount = 128; 48 } 49 return threadCount; 50 } 51 52 TEST(debuggerd_client, race) { 53 static int THREAD_COUNT = getThreadCount(); 54 pid_t forkpid = fork(); 55 56 ASSERT_NE(-1, forkpid); 57 58 if (forkpid == 0) { 59 // Spawn a bunch of threads, to make crash_dump take longer. 60 std::vector<std::thread> threads; 61 for (int i = 0; i < THREAD_COUNT; ++i) { 62 threads.emplace_back([]() { 63 while (true) { 64 std::this_thread::sleep_for(60s); 65 } 66 }); 67 } 68 69 std::this_thread::sleep_for(60s); 70 exit(0); 71 } 72 73 unique_fd pipe_read, pipe_write; 74 ASSERT_TRUE(Pipe(&pipe_read, &pipe_write)); 75 76 // 64 kB should be enough for everyone. 77 constexpr int PIPE_SIZE = 64 * 1024 * 1024; 78 ASSERT_EQ(PIPE_SIZE, fcntl(pipe_read.get(), F_SETPIPE_SZ, PIPE_SIZE)); 79 80 // Wait for a bit to let the child spawn all of its threads. 81 std::this_thread::sleep_for(250ms); 82 83 ASSERT_TRUE( 84 debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 10000, std::move(pipe_write))); 85 // Immediately kill the forked child, to make sure that the dump didn't return early. 86 ASSERT_EQ(0, kill(forkpid, SIGKILL)) << strerror(errno); 87 88 // Check the output. 89 std::string result; 90 ASSERT_TRUE(android::base::ReadFdToString(pipe_read.get(), &result)); 91 92 // Look for "----- end <PID> -----" 93 int found_end = 0; 94 95 std::string expected_end = android::base::StringPrintf("----- end %d -----", forkpid); 96 97 std::vector<std::string> lines = android::base::Split(result, "\n"); 98 for (const std::string& line : lines) { 99 if (line == expected_end) { 100 ++found_end; 101 } 102 } 103 104 EXPECT_EQ(1, found_end) << "\nOutput: \n" << result; 105 } 106 107 TEST(debuggerd_client, no_timeout) { 108 unique_fd pipe_read, pipe_write; 109 ASSERT_TRUE(Pipe(&pipe_read, &pipe_write)); 110 111 pid_t forkpid = fork(); 112 ASSERT_NE(-1, forkpid); 113 if (forkpid == 0) { 114 pipe_write.reset(); 115 char dummy; 116 TEMP_FAILURE_RETRY(read(pipe_read.get(), &dummy, sizeof(dummy))); 117 exit(0); 118 } 119 120 pipe_read.reset(); 121 122 unique_fd output_read, output_write; 123 ASSERT_TRUE(Pipe(&output_read, &output_write)); 124 ASSERT_TRUE( 125 debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 0, std::move(output_write))); 126 } 127