/* * Copyright 2017, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" using namespace std::chrono_literals; using android::base::unique_fd; static int getThreadCount() { int threadCount = 1024; std::vector characteristics = android::base::Split(android::base::GetProperty("ro.build.characteristics", ""), ","); if (std::find(characteristics.begin(), characteristics.end(), "embedded") != characteristics.end()) { // 128 is the realistic number for iot devices. threadCount = 128; } return threadCount; } TEST(debuggerd_client, race) { static int THREAD_COUNT = getThreadCount(); pid_t forkpid = fork(); ASSERT_NE(-1, forkpid); if (forkpid == 0) { // Spawn a bunch of threads, to make crash_dump take longer. std::vector threads; for (int i = 0; i < THREAD_COUNT; ++i) { threads.emplace_back([]() { while (true) { std::this_thread::sleep_for(60s); } }); } std::this_thread::sleep_for(60s); exit(0); } unique_fd pipe_read, pipe_write; ASSERT_TRUE(Pipe(&pipe_read, &pipe_write)); // 16 MiB should be enough for everyone. constexpr int PIPE_SIZE = 16 * 1024 * 1024; ASSERT_EQ(PIPE_SIZE, fcntl(pipe_read.get(), F_SETPIPE_SZ, PIPE_SIZE)); // Wait for a bit to let the child spawn all of its threads. std::this_thread::sleep_for(1s); ASSERT_TRUE( debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 60000, std::move(pipe_write))); // Immediately kill the forked child, to make sure that the dump didn't return early. ASSERT_EQ(0, kill(forkpid, SIGKILL)) << strerror(errno); // Check the output. std::string result; ASSERT_TRUE(android::base::ReadFdToString(pipe_read.get(), &result)); // Look for "----- end -----" int found_end = 0; std::string expected_end = android::base::StringPrintf("----- end %d -----", forkpid); std::vector lines = android::base::Split(result, "\n"); for (const std::string& line : lines) { if (line == expected_end) { ++found_end; } } EXPECT_EQ(1, found_end) << "\nOutput: \n" << result; } TEST(debuggerd_client, no_timeout) { unique_fd pipe_read, pipe_write; ASSERT_TRUE(Pipe(&pipe_read, &pipe_write)); pid_t forkpid = fork(); ASSERT_NE(-1, forkpid); if (forkpid == 0) { pipe_write.reset(); char dummy; TEMP_FAILURE_RETRY(read(pipe_read.get(), &dummy, sizeof(dummy))); exit(0); } pipe_read.reset(); unique_fd output_read, output_write; ASSERT_TRUE(Pipe(&output_read, &output_write)); ASSERT_TRUE( debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 0, std::move(output_write))); }