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