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/stringprintf.h>
31 #include <android-base/strings.h>
32 #include <android-base/unique_fd.h>
33
34 #include <debuggerd/util.h>
35
36 using namespace std::chrono_literals;
37 using android::base::unique_fd;
38
TEST(debuggerd_client,race)39 TEST(debuggerd_client, race) {
40 static constexpr int THREAD_COUNT = 1024;
41 pid_t forkpid = fork();
42
43 ASSERT_NE(-1, forkpid);
44
45 if (forkpid == 0) {
46 // Spawn a bunch of threads, to make crash_dump take longer.
47 std::vector<std::thread> threads;
48 for (int i = 0; i < THREAD_COUNT; ++i) {
49 threads.emplace_back([]() {
50 while (true) {
51 std::this_thread::sleep_for(60s);
52 }
53 });
54 }
55
56 std::this_thread::sleep_for(60s);
57 exit(0);
58 }
59
60 unique_fd pipe_read, pipe_write;
61 ASSERT_TRUE(Pipe(&pipe_read, &pipe_write));
62
63 // 64 kB should be enough for everyone.
64 constexpr int PIPE_SIZE = 64 * 1024 * 1024;
65 ASSERT_EQ(PIPE_SIZE, fcntl(pipe_read.get(), F_SETPIPE_SZ, PIPE_SIZE));
66
67 // Wait for a bit to let the child spawn all of its threads.
68 std::this_thread::sleep_for(250ms);
69
70 ASSERT_TRUE(debuggerd_trigger_dump(forkpid, std::move(pipe_write), kDebuggerdBacktrace, 10000));
71 // Immediately kill the forked child, to make sure that the dump didn't return early.
72 ASSERT_EQ(0, kill(forkpid, SIGKILL)) << strerror(errno);
73
74 // Check the output.
75 std::string result;
76 ASSERT_TRUE(android::base::ReadFdToString(pipe_read.get(), &result));
77
78 // Look for "----- end <PID> -----"
79 int found_end = 0;
80
81 std::string expected_end = android::base::StringPrintf("----- end %d -----", forkpid);
82
83 std::vector<std::string> lines = android::base::Split(result, "\n");
84 for (const std::string& line : lines) {
85 if (line == expected_end) {
86 ++found_end;
87 }
88 }
89
90 EXPECT_EQ(1, found_end) << "\nOutput: \n" << result;
91 }
92
TEST(debuggerd_client,no_timeout)93 TEST(debuggerd_client, no_timeout) {
94 unique_fd pipe_read, pipe_write;
95 ASSERT_TRUE(Pipe(&pipe_read, &pipe_write));
96
97 pid_t forkpid = fork();
98 ASSERT_NE(-1, forkpid);
99 if (forkpid == 0) {
100 pipe_write.reset();
101 char dummy;
102 TEMP_FAILURE_RETRY(read(pipe_read.get(), &dummy, sizeof(dummy)));
103 exit(0);
104 }
105
106 pipe_read.reset();
107
108 unique_fd output_read, output_write;
109 ASSERT_TRUE(Pipe(&output_read, &output_write));
110 ASSERT_TRUE(debuggerd_trigger_dump(forkpid, std::move(output_write), kDebuggerdBacktrace, 0));
111 }
112