1 /*
2  * Copyright (C) 2018 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 "src/traced/probes/ftrace/atrace_wrapper.h"
18 
19 #include <fcntl.h>
20 #include <poll.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <unistd.h>
27 
28 #include "perfetto/base/logging.h"
29 #include "perfetto/base/time.h"
30 #include "perfetto/ext/base/pipe.h"
31 #include "perfetto/ext/base/utils.h"
32 
33 namespace perfetto {
34 
35 namespace {
36 
37 RunAtraceFunction g_run_atrace_for_testing = nullptr;
38 
39 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
40 // Args should include "atrace" for argv[0].
ExecvAtrace(const std::vector<std::string> & args)41 bool ExecvAtrace(const std::vector<std::string>& args) {
42   int status = 1;
43 
44   std::vector<char*> argv;
45   // args, and then a null.
46   argv.reserve(1 + args.size());
47   for (const auto& arg : args)
48     argv.push_back(const_cast<char*>(arg.c_str()));
49   argv.push_back(nullptr);
50 
51   // Create the pipe for the child process to return stderr.
52   base::Pipe err_pipe = base::Pipe::Create(base::Pipe::kRdNonBlock);
53 
54   pid_t pid = fork();
55   PERFETTO_CHECK(pid >= 0);
56   if (pid == 0) {
57     // Duplicate the write end of the pipe into stderr.
58     if ((dup2(*err_pipe.wr, STDERR_FILENO) == -1)) {
59       const char kError[] = "Unable to duplicate stderr fd";
60       base::ignore_result(write(*err_pipe.wr, kError, sizeof(kError)));
61       _exit(1);
62     }
63 
64     int null_fd = open("/dev/null", O_RDWR);
65     if (null_fd == -1) {
66       const char kError[] = "Unable to open dev null";
67       base::ignore_result(write(*err_pipe.wr, kError, sizeof(kError)));
68       _exit(1);
69     }
70 
71     if ((dup2(null_fd, STDOUT_FILENO) == -1)) {
72       const char kError[] = "Unable to duplicate stdout fd";
73       base::ignore_result(write(*err_pipe.wr, kError, sizeof(kError)));
74       _exit(1);
75     }
76 
77     if ((dup2(null_fd, STDIN_FILENO) == -1)) {
78       const char kError[] = "Unable to duplicate stdin fd";
79       base::ignore_result(write(*err_pipe.wr, kError, sizeof(kError)));
80       _exit(1);
81     }
82 
83     // Close stdin/out + any file descriptor that we might have mistakenly
84     // not marked as FD_CLOEXEC. |err_pipe| is FD_CLOEXEC and will be
85     // automatically closed on exec.
86     for (int i = 0; i < 128; i++) {
87       if (i != STDIN_FILENO && i != STDERR_FILENO && i != STDOUT_FILENO)
88         close(i);
89     }
90 
91     execv("/system/bin/atrace", &argv[0]);
92 
93     // Reached only if execv fails.
94     _exit(1);
95   }
96 
97   // Close the write end of the pipe.
98   err_pipe.wr.reset();
99 
100   // Collect the output from child process.
101   char buffer[4096];
102   std::string error;
103 
104   // Get the read end of the pipe.
105   constexpr uint8_t kFdCount = 1;
106   struct pollfd fds[kFdCount]{};
107   fds[0].fd = *err_pipe.rd;
108   fds[0].events = POLLIN;
109 
110   // Store the start time of atrace and setup the timeout.
111   constexpr auto timeout = base::TimeMillis(20000);
112   auto start = base::GetWallTimeMs();
113   for (;;) {
114     // Check if we are below the timeout and update the select timeout to
115     // the time remaining.
116     auto now = base::GetWallTimeMs();
117     auto remaining = timeout - (now - start);
118     auto timeout_ms = static_cast<int>(remaining.count());
119     if (timeout_ms <= 0) {
120       // Kill atrace.
121       kill(pid, SIGKILL);
122 
123       std::string cmdline = "/system/bin/atrace";
124       for (const auto& arg : args) {
125         cmdline += " " + arg;
126       }
127       error.append("Timed out waiting for atrace (cmdline: " + cmdline + ")");
128       break;
129     }
130 
131     // Wait for the value of the timeout.
132     auto ret = poll(fds, kFdCount, timeout_ms);
133     if (ret == 0 || (ret < 0 && errno == EINTR)) {
134       // Either timeout occurred in poll (in which case continue so that this
135       // will be picked up by our own timeout logic) or we received an EINTR and
136       // we should try again.
137       continue;
138     } else if (ret < 0) {
139       error.append("Error while polling atrace stderr");
140       break;
141     }
142 
143     // Data is available to be read from the fd.
144     int64_t count = PERFETTO_EINTR(read(*err_pipe.rd, buffer, sizeof(buffer)));
145     if (ret < 0 && errno == EAGAIN) {
146       continue;
147     } else if (count < 0) {
148       error.append("Error while reading atrace stderr");
149       break;
150     } else if (count == 0) {
151       // EOF so we can exit this loop.
152       break;
153     }
154     error.append(buffer, static_cast<size_t>(count));
155   }
156 
157   // Wait until the child process exits fully.
158   PERFETTO_EINTR(waitpid(pid, &status, 0));
159 
160   bool ok = WIFEXITED(status) && WEXITSTATUS(status) == 0;
161   if (!ok) {
162     // TODO(lalitm): use the stderr result from atrace.
163     PERFETTO_ELOG("%s", error.c_str());
164   }
165   return ok;
166 }
167 #endif
168 
169 }  // namespace
170 
RunAtrace(const std::vector<std::string> & args)171 bool RunAtrace(const std::vector<std::string>& args) {
172   if (g_run_atrace_for_testing)
173     return g_run_atrace_for_testing(args);
174 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
175   return ExecvAtrace(args);
176 #else
177   PERFETTO_LOG("Atrace only supported on Android.");
178   return false;
179 #endif
180 }
181 
SetRunAtraceForTesting(RunAtraceFunction f)182 void SetRunAtraceForTesting(RunAtraceFunction f) {
183   g_run_atrace_for_testing = f;
184 }
185 
186 }  // namespace perfetto
187