1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
18*6dbdd20aSAndroid Build Coastguard Worker #include <cstdint>
19*6dbdd20aSAndroid Build Coastguard Worker #include <cstdio>
20*6dbdd20aSAndroid Build Coastguard Worker #include <cstdlib>
21*6dbdd20aSAndroid Build Coastguard Worker #include <cstring>
22*6dbdd20aSAndroid Build Coastguard Worker #include <string>
23*6dbdd20aSAndroid Build Coastguard Worker
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/proc_utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/pipe.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/subprocess.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/traced/traced.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "src/perfetto_cmd/perfetto_cmd.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "src/websocket_bridge/websocket_bridge.h"
34*6dbdd20aSAndroid Build Coastguard Worker
35*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_TRACED_PERF)
36*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/traced_perf.h"
37*6dbdd20aSAndroid Build Coastguard Worker #endif
38*6dbdd20aSAndroid Build Coastguard Worker
39*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
40*6dbdd20aSAndroid Build Coastguard Worker namespace {
41*6dbdd20aSAndroid Build Coastguard Worker
42*6dbdd20aSAndroid Build Coastguard Worker struct Applet {
43*6dbdd20aSAndroid Build Coastguard Worker using MainFunction = int (*)(int /*argc*/, char** /*argv*/);
44*6dbdd20aSAndroid Build Coastguard Worker const char* name;
45*6dbdd20aSAndroid Build Coastguard Worker MainFunction entrypoint;
46*6dbdd20aSAndroid Build Coastguard Worker };
47*6dbdd20aSAndroid Build Coastguard Worker
48*6dbdd20aSAndroid Build Coastguard Worker const Applet g_applets[]{
49*6dbdd20aSAndroid Build Coastguard Worker {"traced", ServiceMain},
50*6dbdd20aSAndroid Build Coastguard Worker {"traced_probes", ProbesMain},
51*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_TRACED_PERF)
52*6dbdd20aSAndroid Build Coastguard Worker {"traced_perf", TracedPerfMain},
53*6dbdd20aSAndroid Build Coastguard Worker #endif
54*6dbdd20aSAndroid Build Coastguard Worker {"perfetto", PerfettoCmdMain},
55*6dbdd20aSAndroid Build Coastguard Worker {"trigger_perfetto", TriggerPerfettoMain},
56*6dbdd20aSAndroid Build Coastguard Worker {"websocket_bridge", WebsocketBridgeMain},
57*6dbdd20aSAndroid Build Coastguard Worker };
58*6dbdd20aSAndroid Build Coastguard Worker
PrintUsage()59*6dbdd20aSAndroid Build Coastguard Worker void PrintUsage() {
60*6dbdd20aSAndroid Build Coastguard Worker printf(R"(Welcome to Perfetto tracing!
61*6dbdd20aSAndroid Build Coastguard Worker
62*6dbdd20aSAndroid Build Coastguard Worker Tracebox is a bundle containing all the tracing services and the perfetto
63*6dbdd20aSAndroid Build Coastguard Worker cmdline client in one binary. It can be used either to spawn manually the
64*6dbdd20aSAndroid Build Coastguard Worker various subprocess or in "autostart" mode, which will take care of starting
65*6dbdd20aSAndroid Build Coastguard Worker and tearing down the services for you.
66*6dbdd20aSAndroid Build Coastguard Worker
67*6dbdd20aSAndroid Build Coastguard Worker Usage in autostart mode:
68*6dbdd20aSAndroid Build Coastguard Worker tracebox -t 10s -o trace_file.perfetto-trace sched/sched_switch
69*6dbdd20aSAndroid Build Coastguard Worker See tracebox --help for more options.
70*6dbdd20aSAndroid Build Coastguard Worker
71*6dbdd20aSAndroid Build Coastguard Worker Usage in manual mode:
72*6dbdd20aSAndroid Build Coastguard Worker tracebox applet_name [args ...] (e.g. ./tracebox traced --help)
73*6dbdd20aSAndroid Build Coastguard Worker Applets:)");
74*6dbdd20aSAndroid Build Coastguard Worker
75*6dbdd20aSAndroid Build Coastguard Worker for (const Applet& applet : g_applets)
76*6dbdd20aSAndroid Build Coastguard Worker printf(" %s", applet.name);
77*6dbdd20aSAndroid Build Coastguard Worker
78*6dbdd20aSAndroid Build Coastguard Worker printf(R"(
79*6dbdd20aSAndroid Build Coastguard Worker
80*6dbdd20aSAndroid Build Coastguard Worker See also:
81*6dbdd20aSAndroid Build Coastguard Worker * https://perfetto.dev/docs/
82*6dbdd20aSAndroid Build Coastguard Worker * The config editor in the record page of https://ui.perfetto.dev/
83*6dbdd20aSAndroid Build Coastguard Worker )");
84*6dbdd20aSAndroid Build Coastguard Worker }
85*6dbdd20aSAndroid Build Coastguard Worker
PrintTraceboxUsage()86*6dbdd20aSAndroid Build Coastguard Worker void PrintTraceboxUsage() {
87*6dbdd20aSAndroid Build Coastguard Worker printf(R"(
88*6dbdd20aSAndroid Build Coastguard Worker Tracebox-specific args
89*6dbdd20aSAndroid Build Coastguard Worker --system-sockets : Forces the use of system-sockets when using autostart
90*6dbdd20aSAndroid Build Coastguard Worker mode. Cannot be used in applet mode.
91*6dbdd20aSAndroid Build Coastguard Worker )");
92*6dbdd20aSAndroid Build Coastguard Worker }
93*6dbdd20aSAndroid Build Coastguard Worker
TraceboxMain(int argc,char ** argv)94*6dbdd20aSAndroid Build Coastguard Worker int TraceboxMain(int argc, char** argv) {
95*6dbdd20aSAndroid Build Coastguard Worker // Manual mode: if either the 1st argument (argv[1]) or the exe name (argv[0])
96*6dbdd20aSAndroid Build Coastguard Worker // match the name of an applet, directly invoke that without further
97*6dbdd20aSAndroid Build Coastguard Worker // modifications.
98*6dbdd20aSAndroid Build Coastguard Worker
99*6dbdd20aSAndroid Build Coastguard Worker // Extract the file name from argv[0].
100*6dbdd20aSAndroid Build Coastguard Worker char* slash = strrchr(argv[0], '/');
101*6dbdd20aSAndroid Build Coastguard Worker char* argv0 = slash ? slash + 1 : argv[0];
102*6dbdd20aSAndroid Build Coastguard Worker
103*6dbdd20aSAndroid Build Coastguard Worker for (const Applet& applet : g_applets) {
104*6dbdd20aSAndroid Build Coastguard Worker if (!strcmp(argv0, applet.name))
105*6dbdd20aSAndroid Build Coastguard Worker return applet.entrypoint(argc, argv);
106*6dbdd20aSAndroid Build Coastguard Worker if (argc > 1 && !strcmp(argv[1], applet.name))
107*6dbdd20aSAndroid Build Coastguard Worker return applet.entrypoint(argc - 1, &argv[1]);
108*6dbdd20aSAndroid Build Coastguard Worker }
109*6dbdd20aSAndroid Build Coastguard Worker
110*6dbdd20aSAndroid Build Coastguard Worker // If no matching applet is found, switch to the autostart mode. In this mode
111*6dbdd20aSAndroid Build Coastguard Worker // we make tracebox behave like the cmdline client (without needing to prefix
112*6dbdd20aSAndroid Build Coastguard Worker // it with "perfetto"), but will also start traced and traced_probes.
113*6dbdd20aSAndroid Build Coastguard Worker // As part of this we also use a different namespace for the producer/consumer
114*6dbdd20aSAndroid Build Coastguard Worker // sockets, to avoid clashing with the system daemon.
115*6dbdd20aSAndroid Build Coastguard Worker
116*6dbdd20aSAndroid Build Coastguard Worker if (argc <= 1) {
117*6dbdd20aSAndroid Build Coastguard Worker PrintUsage();
118*6dbdd20aSAndroid Build Coastguard Worker return 1;
119*6dbdd20aSAndroid Build Coastguard Worker }
120*6dbdd20aSAndroid Build Coastguard Worker
121*6dbdd20aSAndroid Build Coastguard Worker auto* end = std::remove_if(argv, argv + argc, [](char* arg) {
122*6dbdd20aSAndroid Build Coastguard Worker return !strcmp(arg, "--system-sockets");
123*6dbdd20aSAndroid Build Coastguard Worker });
124*6dbdd20aSAndroid Build Coastguard Worker if (end < (argv + argc - 1)) {
125*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Cannot specify --system-sockets multiple times");
126*6dbdd20aSAndroid Build Coastguard Worker return 1;
127*6dbdd20aSAndroid Build Coastguard Worker }
128*6dbdd20aSAndroid Build Coastguard Worker if (bool system_sockets = end == (argv + argc - 1); system_sockets) {
129*6dbdd20aSAndroid Build Coastguard Worker argc--;
130*6dbdd20aSAndroid Build Coastguard Worker } else {
131*6dbdd20aSAndroid Build Coastguard Worker auto pid_str = std::to_string(static_cast<uint64_t>(base::GetProcessId()));
132*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
133*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
134*6dbdd20aSAndroid Build Coastguard Worker // Use an unlinked abstract domain socket on Linux/Android.
135*6dbdd20aSAndroid Build Coastguard Worker std::string consumer_socket = "@traced-c-" + pid_str;
136*6dbdd20aSAndroid Build Coastguard Worker std::string producer_socket = "@traced-p-" + pid_str;
137*6dbdd20aSAndroid Build Coastguard Worker #elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
138*6dbdd20aSAndroid Build Coastguard Worker std::string consumer_socket = "/tmp/traced-c-" + pid_str;
139*6dbdd20aSAndroid Build Coastguard Worker std::string producer_socket = "/tmp/traced-p-" + pid_str;
140*6dbdd20aSAndroid Build Coastguard Worker #else
141*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL("The autostart mode is not supported on this platform");
142*6dbdd20aSAndroid Build Coastguard Worker #endif
143*6dbdd20aSAndroid Build Coastguard Worker
144*6dbdd20aSAndroid Build Coastguard Worker // If the caller has set the PERFETTO_*_SOCK_NAME, respect those.
145*6dbdd20aSAndroid Build Coastguard Worker if (const char* env = getenv("PERFETTO_CONSUMER_SOCK_NAME"); env) {
146*6dbdd20aSAndroid Build Coastguard Worker consumer_socket = env;
147*6dbdd20aSAndroid Build Coastguard Worker }
148*6dbdd20aSAndroid Build Coastguard Worker if (const char* env = getenv("PERFETTO_PRODUCER_SOCK_NAME"); env) {
149*6dbdd20aSAndroid Build Coastguard Worker producer_socket = env;
150*6dbdd20aSAndroid Build Coastguard Worker }
151*6dbdd20aSAndroid Build Coastguard Worker base::SetEnv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket);
152*6dbdd20aSAndroid Build Coastguard Worker base::SetEnv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket);
153*6dbdd20aSAndroid Build Coastguard Worker }
154*6dbdd20aSAndroid Build Coastguard Worker
155*6dbdd20aSAndroid Build Coastguard Worker PerfettoCmd perfetto_cmd;
156*6dbdd20aSAndroid Build Coastguard Worker
157*6dbdd20aSAndroid Build Coastguard Worker // If the cmdline parsing fails, stop here, no need to spawn services.
158*6dbdd20aSAndroid Build Coastguard Worker // It will daemonize if --background. In that case the subprocesses will be
159*6dbdd20aSAndroid Build Coastguard Worker // spawned by the damonized cmdline client, which is what we want so killing
160*6dbdd20aSAndroid Build Coastguard Worker // the backgrounded cmdline client will also kill the other services, as they
161*6dbdd20aSAndroid Build Coastguard Worker // will live in the same background session.
162*6dbdd20aSAndroid Build Coastguard Worker auto opt_res = perfetto_cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
163*6dbdd20aSAndroid Build Coastguard Worker if (opt_res.has_value()) {
164*6dbdd20aSAndroid Build Coastguard Worker if (*opt_res != 0) {
165*6dbdd20aSAndroid Build Coastguard Worker PrintTraceboxUsage();
166*6dbdd20aSAndroid Build Coastguard Worker }
167*6dbdd20aSAndroid Build Coastguard Worker return *opt_res;
168*6dbdd20aSAndroid Build Coastguard Worker }
169*6dbdd20aSAndroid Build Coastguard Worker
170*6dbdd20aSAndroid Build Coastguard Worker std::string self_path = base::GetCurExecutablePath();
171*6dbdd20aSAndroid Build Coastguard Worker base::Subprocess traced({self_path, "traced"});
172*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
173*6dbdd20aSAndroid Build Coastguard Worker // |traced_sync_pipe| is used to synchronize with traced socket creation.
174*6dbdd20aSAndroid Build Coastguard Worker // traced will write "1" and close the FD when the IPC socket is listening
175*6dbdd20aSAndroid Build Coastguard Worker // (or traced crashed).
176*6dbdd20aSAndroid Build Coastguard Worker base::Pipe traced_sync_pipe = base::Pipe::Create();
177*6dbdd20aSAndroid Build Coastguard Worker int traced_fd = *traced_sync_pipe.wr;
178*6dbdd20aSAndroid Build Coastguard Worker base::SetEnv("TRACED_NOTIFY_FD", std::to_string(traced_fd));
179*6dbdd20aSAndroid Build Coastguard Worker traced.args.preserve_fds.emplace_back(traced_fd);
180*6dbdd20aSAndroid Build Coastguard Worker // Create a new process group so CTRL-C is delivered only to the cmdline
181*6dbdd20aSAndroid Build Coastguard Worker // process (the tracebox one) and not to traced. traced will still exit once
182*6dbdd20aSAndroid Build Coastguard Worker // the main process exits, but this allows graceful stopping of the trace
183*6dbdd20aSAndroid Build Coastguard Worker // without abruptedly killing traced{,probes} when hitting CTRL+C.
184*6dbdd20aSAndroid Build Coastguard Worker traced.args.posix_proc_group_id = 0; // 0 = start a new process group.
185*6dbdd20aSAndroid Build Coastguard Worker #endif
186*6dbdd20aSAndroid Build Coastguard Worker traced.Start();
187*6dbdd20aSAndroid Build Coastguard Worker
188*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
189*6dbdd20aSAndroid Build Coastguard Worker traced_sync_pipe.wr.reset();
190*6dbdd20aSAndroid Build Coastguard Worker
191*6dbdd20aSAndroid Build Coastguard Worker std::string traced_notify_msg;
192*6dbdd20aSAndroid Build Coastguard Worker base::ReadPlatformHandle(*traced_sync_pipe.rd, &traced_notify_msg);
193*6dbdd20aSAndroid Build Coastguard Worker if (traced_notify_msg != "1")
194*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL("The tracing service failed unexpectedly. Check the logs");
195*6dbdd20aSAndroid Build Coastguard Worker #endif
196*6dbdd20aSAndroid Build Coastguard Worker
197*6dbdd20aSAndroid Build Coastguard Worker base::Subprocess traced_probes(
198*6dbdd20aSAndroid Build Coastguard Worker {self_path, "traced_probes", "--reset-ftrace"});
199*6dbdd20aSAndroid Build Coastguard Worker // Put traced_probes in the same process group as traced. Same reason (CTRL+C)
200*6dbdd20aSAndroid Build Coastguard Worker // but it's not worth creating a new group.
201*6dbdd20aSAndroid Build Coastguard Worker traced_probes.args.posix_proc_group_id = traced.pid();
202*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
203*6dbdd20aSAndroid Build Coastguard Worker // |traced_probes_sync_pipe| is used to synchronize with traced socket
204*6dbdd20aSAndroid Build Coastguard Worker // creation. traced will write "1" and close the FD when the IPC socket is
205*6dbdd20aSAndroid Build Coastguard Worker // listening (or traced crashed).
206*6dbdd20aSAndroid Build Coastguard Worker base::Pipe traced_probes_sync_pipe = base::Pipe::Create();
207*6dbdd20aSAndroid Build Coastguard Worker int traced_probes_fd = *traced_probes_sync_pipe.wr;
208*6dbdd20aSAndroid Build Coastguard Worker base::SetEnv("TRACED_PROBES_NOTIFY_FD", std::to_string(traced_probes_fd));
209*6dbdd20aSAndroid Build Coastguard Worker traced_probes.args.preserve_fds.emplace_back(traced_probes_fd);
210*6dbdd20aSAndroid Build Coastguard Worker #endif
211*6dbdd20aSAndroid Build Coastguard Worker traced_probes.Start();
212*6dbdd20aSAndroid Build Coastguard Worker
213*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
214*6dbdd20aSAndroid Build Coastguard Worker traced_probes_sync_pipe.wr.reset();
215*6dbdd20aSAndroid Build Coastguard Worker
216*6dbdd20aSAndroid Build Coastguard Worker std::string traced_probes_notify_msg;
217*6dbdd20aSAndroid Build Coastguard Worker base::ReadPlatformHandle(*traced_probes_sync_pipe.rd,
218*6dbdd20aSAndroid Build Coastguard Worker &traced_probes_notify_msg);
219*6dbdd20aSAndroid Build Coastguard Worker if (traced_probes_notify_msg != "1")
220*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL(
221*6dbdd20aSAndroid Build Coastguard Worker "The traced_probes service failed unexpectedly. Check the logs");
222*6dbdd20aSAndroid Build Coastguard Worker #endif
223*6dbdd20aSAndroid Build Coastguard Worker
224*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_TRACED_PERF)
225*6dbdd20aSAndroid Build Coastguard Worker base::Subprocess traced_perf({self_path, "traced_perf"});
226*6dbdd20aSAndroid Build Coastguard Worker // Put traced_perf in the same process group as traced. Same reason (CTRL+C)
227*6dbdd20aSAndroid Build Coastguard Worker // but it's not worth creating a new group.
228*6dbdd20aSAndroid Build Coastguard Worker traced_perf.args.posix_proc_group_id = traced.pid();
229*6dbdd20aSAndroid Build Coastguard Worker
230*6dbdd20aSAndroid Build Coastguard Worker base::Pipe traced_perf_sync_pipe = base::Pipe::Create();
231*6dbdd20aSAndroid Build Coastguard Worker int traced_perf_fd = *traced_perf_sync_pipe.wr;
232*6dbdd20aSAndroid Build Coastguard Worker base::SetEnv("TRACED_PERF_NOTIFY_FD", std::to_string(traced_perf_fd));
233*6dbdd20aSAndroid Build Coastguard Worker traced_perf.args.preserve_fds.emplace_back(traced_perf_fd);
234*6dbdd20aSAndroid Build Coastguard Worker traced_perf.Start();
235*6dbdd20aSAndroid Build Coastguard Worker traced_perf_sync_pipe.wr.reset();
236*6dbdd20aSAndroid Build Coastguard Worker
237*6dbdd20aSAndroid Build Coastguard Worker std::string traced_perf_notify_msg;
238*6dbdd20aSAndroid Build Coastguard Worker base::ReadPlatformHandle(*traced_perf_sync_pipe.rd, &traced_perf_notify_msg);
239*6dbdd20aSAndroid Build Coastguard Worker if (traced_perf_notify_msg != "1")
240*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL(
241*6dbdd20aSAndroid Build Coastguard Worker "The traced_perf service failed unexpectedly. Check the logs");
242*6dbdd20aSAndroid Build Coastguard Worker #endif
243*6dbdd20aSAndroid Build Coastguard Worker
244*6dbdd20aSAndroid Build Coastguard Worker perfetto_cmd.ConnectToServiceRunAndMaybeNotify();
245*6dbdd20aSAndroid Build Coastguard Worker return 0;
246*6dbdd20aSAndroid Build Coastguard Worker }
247*6dbdd20aSAndroid Build Coastguard Worker
248*6dbdd20aSAndroid Build Coastguard Worker } // namespace
249*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
250*6dbdd20aSAndroid Build Coastguard Worker
main(int argc,char ** argv)251*6dbdd20aSAndroid Build Coastguard Worker int main(int argc, char** argv) {
252*6dbdd20aSAndroid Build Coastguard Worker return perfetto::TraceboxMain(argc, argv);
253*6dbdd20aSAndroid Build Coastguard Worker }
254