xref: /aosp_15_r20/external/perfetto/src/traced_relay/relay_service_main.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2023 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 "perfetto/ext/base/file_utils.h"
18 #include "perfetto/ext/base/getopt.h"
19 #include "perfetto/ext/base/string_utils.h"
20 #include "perfetto/ext/base/unix_task_runner.h"
21 #include "perfetto/ext/base/version.h"
22 #include "perfetto/ext/base/watchdog.h"
23 #include "perfetto/ext/traced/traced.h"
24 #include "perfetto/tracing/default_socket.h"
25 #include "src/traced_relay/relay_service.h"
26 
27 namespace perfetto {
28 namespace {
PrintUsage(const char * prog_name)29 void PrintUsage(const char* prog_name) {
30   fprintf(stderr, R"(
31 Relays trace data to a remote tracing service. Cannot run alongside the "traced"
32 daemon.
33 
34 Usage: %s [OPTION]...
35 
36 Options:
37   --background
38       Run as a background process.
39   --set-socket-permissions <GROUP>:<MODE>
40       Set group ownership and permissions for the listening socket.
41       Example: traced-producer:0660 (rw-rw----)
42   --version
43       Display version information and exit.
44 
45 Environment Variable:
46   PERFETTO_RELAY_SOCK_NAME
47       Socket name of the remote tracing service.
48       Example: 192.168.0.1:20001 or vsock://2:20001
49 
50 Example:
51   PERFETTO_RELAY_SOCK_NAME=192.168.0.1:20001 %s \
52       --set-socket-permissions traced-producer:0660
53 
54   Starts the service, relaying trace data to 192.168.0.1:20001.
55   The local listening socket's group is set to "traced-producer" with
56   permissions 0660.
57 )",
58           prog_name, prog_name);
59 }
60 
61 }  // namespace
62 
RelayServiceMain(int argc,char ** argv)63 static int RelayServiceMain(int argc, char** argv) {
64   enum LongOption {
65     OPT_VERSION = 1000,
66     OPT_SET_SOCKET_PERMISSIONS = 1001,
67     OPT_BACKGROUND,
68   };
69 
70   bool background = false;
71 
72   static const option long_options[] = {
73       {"background", no_argument, nullptr, OPT_BACKGROUND},
74       {"version", no_argument, nullptr, OPT_VERSION},
75       {"set-socket-permissions", required_argument, nullptr,
76        OPT_SET_SOCKET_PERMISSIONS},
77       {nullptr, 0, nullptr, 0}};
78 
79   std::string listen_socket_group, listen_socket_mode_bits;
80 
81   for (;;) {
82     int option = getopt_long(argc, argv, "", long_options, nullptr);
83     if (option == -1)
84       break;
85     switch (option) {
86       case OPT_BACKGROUND:
87         background = true;
88         break;
89       case OPT_VERSION:
90         printf("%s\n", base::GetVersionString());
91         return 0;
92       case OPT_SET_SOCKET_PERMISSIONS: {
93         // Check that the socket permission argument is well formed.
94         auto parts = perfetto::base::SplitString(std::string(optarg), ":");
95         PERFETTO_CHECK(parts.size() == 2);
96         PERFETTO_CHECK(
97             std::all_of(parts.cbegin(), parts.cend(),
98                         [](const std::string& part) { return !part.empty(); }));
99         listen_socket_group = parts[0];
100         listen_socket_mode_bits = parts[1];
101         break;
102       }
103       default:
104         PrintUsage(argv[0]);
105         return 1;
106     }
107   }
108 
109   if (!GetRelaySocket()) {
110     PrintUsage(argv[0]);
111     return 1;
112   }
113 
114   if (background) {
115     base::Daemonize([] { return 0; });
116   }
117 
118   base::UnixTaskRunner task_runner;
119   auto svc = std::make_unique<RelayService>(&task_runner);
120 
121   // traced_relay binds to the producer socket of the `traced` service. When
122   // built for Android, this socket is created and bound during init, and its
123   // file descriptor is passed through the environment variable.
124   const char* env_prod = getenv("ANDROID_SOCKET_traced_producer");
125   base::ScopedFile producer_fd;
126   if (env_prod) {
127 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
128     PERFETTO_CHECK(false);
129 #else
130     auto opt_fd = base::CStringToInt32(env_prod);
131     if (opt_fd.has_value())
132       producer_fd.reset(*opt_fd);
133 
134     svc->Start(std::move(producer_fd), GetRelaySocket());
135 #endif
136   } else {
137     auto listen_socket = GetProducerSocket();
138     remove(listen_socket);
139     if (!listen_socket_group.empty()) {
140       auto status = base::SetFilePermissions(listen_socket, listen_socket_group,
141                                              listen_socket_mode_bits);
142       if (!status.ok()) {
143         PERFETTO_ELOG("Failed to set socket permissions: %s",
144                       status.c_message());
145         return 1;
146       }
147     }
148 
149     svc->Start(listen_socket, GetRelaySocket());
150   }
151 
152   // Set the CPU limit and start the watchdog running. The memory limit will
153   // be set inside the service code as it relies on the size of buffers.
154   // The CPU limit is the generic one defined in watchdog.h.
155   base::Watchdog* watchdog = base::Watchdog::GetInstance();
156   watchdog->SetCpuLimit(base::kWatchdogDefaultCpuLimit,
157                         base::kWatchdogDefaultCpuWindow);
158   watchdog->Start();
159 
160   PERFETTO_ILOG("Started traced_relay, listening on %s, forwarding to %s",
161                 GetProducerSocket(), GetRelaySocket());
162 
163   task_runner.Run();
164   return 0;
165 }
166 }  // namespace perfetto
167 
main(int argc,char ** argv)168 int main(int argc, char** argv) {
169   return perfetto::RelayServiceMain(argc, argv);
170 }
171