OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The Chromium Authors. All rights reserved. | 2 * Copyright 2015 The Chromium Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include "tools/android/memtrack_helper/memtrack_helper.h" | 7 #include "tools/android/memtrack_helper/memtrack_helper.h" |
8 | 8 |
9 #include <dlfcn.h> | 9 #include <dlfcn.h> |
10 #include <errno.h> | 10 #include <errno.h> |
11 #include <fcntl.h> | 11 #include <fcntl.h> |
12 #include <signal.h> | |
13 #include <stdio.h> | 12 #include <stdio.h> |
14 #include <stdlib.h> | 13 #include <stdlib.h> |
15 #include <string.h> | 14 #include <string.h> |
16 #include <unistd.h> | |
17 #include <sys/socket.h> | 15 #include <sys/socket.h> |
18 #include <sys/un.h> | 16 #include <sys/un.h> |
19 #include <sys/stat.h> | 17 #include <sys/stat.h> |
20 #include <sys/types.h> | 18 #include <sys/types.h> |
21 #include <sys/wait.h> | 19 #include <sys/wait.h> |
22 | 20 |
23 /* | 21 /* |
24 * This is a helper daemon for Android which makes memtrack graphics information | 22 * This is a helper daemon for Android which makes memtrack graphics information |
25 * accessible via a UNIX socket. It is used by telemetry and memory-infra. | 23 * accessible via a UNIX socket. It is used by telemetry and memory-infra. |
26 * More description in the design-doc: https://goo.gl/4Y30p9 . | 24 * More description in the design-doc: https://goo.gl/4Y30p9 . |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 static void send_shutdown_request(struct sockaddr_un* addr) { | 57 static void send_shutdown_request(struct sockaddr_un* addr) { |
60 int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); | 58 int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); |
61 connect(sock, (struct sockaddr*)addr, sizeof(*addr)); | 59 connect(sock, (struct sockaddr*)addr, sizeof(*addr)); |
62 send(sock, &kShutdownRequest, 1, 0); | 60 send(sock, &kShutdownRequest, 1, 0); |
63 close(sock); | 61 close(sock); |
64 } | 62 } |
65 | 63 |
66 static void handle_one_request(int client_sock) { | 64 static void handle_one_request(int client_sock) { |
67 char buf[32]; | 65 char buf[32]; |
68 char response[4096] = ""; | 66 char response[4096] = ""; |
69 ssize_t rsize = recv(client_sock, buf, sizeof(buf), 0); | 67 ssize_t rsize = recv(client_sock, buf, sizeof(buf) - 1, 0); |
70 | |
71 if (rsize < 1) | 68 if (rsize < 1) |
72 return; | 69 return; |
| 70 buf[rsize] = '\0'; |
73 | 71 |
74 if (buf[0] == kShutdownRequest) | 72 if (buf[0] == kShutdownRequest) |
75 exit(EXIT_SUCCESS); | 73 exit(EXIT_SUCCESS); |
76 | 74 |
77 pid_t pid = -1; | 75 pid_t pid = -1; |
78 if (sscanf(buf, "%d", &pid) != 1) | 76 if (sscanf(buf, "%d", &pid) != 1 || pid < 0) |
79 return send_response(client_sock, "ERR invalid pid"); | 77 return send_response(client_sock, "ERR invalid pid"); |
80 | 78 |
81 memtrack_proc_handle handle = memtrack_proc_new(); | 79 memtrack_proc_handle handle = memtrack_proc_new(); |
82 if (!handle) | 80 if (!handle) |
83 return send_response(client_sock, "ERR memtrack_proc_new()"); | 81 return send_response(client_sock, "ERR memtrack_proc_new()"); |
84 | 82 |
85 if (memtrack_proc_get(handle, pid)) { | 83 if (memtrack_proc_get(handle, pid)) { |
86 memtrack_proc_destroy(handle); | 84 memtrack_proc_destroy(handle); |
87 return send_response(client_sock, "ERR memtrack_proc_get()"); | 85 return send_response(client_sock, "ERR memtrack_proc_get()"); |
88 } | 86 } |
89 | 87 |
90 char* response_ptr = &response[0]; | 88 char* response_ptr = &response[0]; |
91 if (memtrack_proc_graphics_total) { | 89 if (memtrack_proc_graphics_total) { |
92 response_ptr += sprintf(response_ptr, "graphics_total %zd\n", | 90 response_ptr += sprintf(response_ptr, "graphics_total %zd\n", |
93 memtrack_proc_graphics_total(handle)); | 91 memtrack_proc_graphics_total(handle)); |
94 } | 92 } |
95 if (memtrack_proc_graphics_pss) { | 93 if (memtrack_proc_graphics_pss) { |
96 response_ptr += sprintf(response_ptr, "graphics_pss %zd\n", | 94 response_ptr += sprintf(response_ptr, "graphics_pss %zd\n", |
97 memtrack_proc_graphics_pss(handle)); | 95 memtrack_proc_graphics_pss(handle)); |
98 } | 96 } |
99 if (memtrack_proc_gl_total) { | 97 if (memtrack_proc_gl_total) { |
100 response_ptr += | 98 response_ptr += sprintf(response_ptr, "gl_total %zd\n", |
101 sprintf(response_ptr, "gl_total %zd\n", memtrack_proc_gl_total(handle)); | 99 memtrack_proc_gl_total(handle)); |
102 } | 100 } |
103 if (memtrack_proc_gl_pss) { | 101 if (memtrack_proc_gl_pss) { |
104 response_ptr += | 102 response_ptr += sprintf(response_ptr, "gl_pss %zd\n", |
105 sprintf(response_ptr, "gl_pss %zd\n", memtrack_proc_gl_pss(handle)); | 103 memtrack_proc_gl_pss(handle)); |
106 } | 104 } |
107 if (memtrack_proc_other_total) { | 105 if (memtrack_proc_other_total) { |
108 response_ptr += sprintf(response_ptr, "other_total %zd\n", | 106 response_ptr += sprintf(response_ptr, "other_total %zd\n", |
109 memtrack_proc_other_total(handle)); | 107 memtrack_proc_other_total(handle)); |
110 } | 108 } |
111 if (memtrack_proc_other_pss) { | 109 if (memtrack_proc_other_pss) { |
112 response_ptr += sprintf(response_ptr, "other_pss %zd\n", | 110 response_ptr += sprintf(response_ptr, "other_pss %zd\n", |
113 memtrack_proc_other_pss(handle)); | 111 memtrack_proc_other_pss(handle)); |
114 } | 112 } |
115 | 113 |
116 memtrack_proc_destroy(handle); | 114 memtrack_proc_destroy(handle); |
117 send_response(client_sock, response); | 115 send_response(client_sock, response); |
118 } | 116 } |
119 | 117 |
120 static void daemonize() { | 118 static void daemonize() { |
121 pid_t pid; | 119 pid_t pid; |
122 | 120 |
123 pid = fork(); | 121 pid = fork(); |
124 if (pid < 0) | 122 if (pid < 0) |
125 exit_with_failure("fork"); | 123 exit_with_failure("fork"); |
126 if (pid > 0) { | 124 if (pid > 0) { |
127 /* Terminate the main process attached to TTY once the daemon re-forks. */ | 125 // Main process keeps TTY while intermediate child do daemonization |
| 126 // because adb can immediately kill a process disconnected from adb's TTY. |
128 int ignore; | 127 int ignore; |
129 wait(&ignore); | 128 wait(&ignore); |
130 exit(EXIT_SUCCESS); | 129 exit(EXIT_SUCCESS); |
131 } | 130 } |
132 | 131 |
133 if (setsid() == -1) | 132 if (setsid() == -1) |
134 exit_with_failure("setsid"); | 133 exit_with_failure("setsid"); |
135 | 134 |
136 chdir("/"); | 135 chdir("/"); |
137 umask(0); | 136 umask(0); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 libhandle, "memtrack_proc_graphics_pss"); | 172 libhandle, "memtrack_proc_graphics_pss"); |
174 memtrack_proc_gl_total = | 173 memtrack_proc_gl_total = |
175 (memtrack_proc_gl_total_t)dlsym(libhandle, "memtrack_proc_gl_total"); | 174 (memtrack_proc_gl_total_t)dlsym(libhandle, "memtrack_proc_gl_total"); |
176 memtrack_proc_gl_pss = | 175 memtrack_proc_gl_pss = |
177 (memtrack_proc_gl_pss_t)dlsym(libhandle, "memtrack_proc_gl_pss"); | 176 (memtrack_proc_gl_pss_t)dlsym(libhandle, "memtrack_proc_gl_pss"); |
178 memtrack_proc_other_total = (memtrack_proc_other_total_t)dlsym( | 177 memtrack_proc_other_total = (memtrack_proc_other_total_t)dlsym( |
179 libhandle, "memtrack_proc_other_total"); | 178 libhandle, "memtrack_proc_other_total"); |
180 memtrack_proc_other_pss = | 179 memtrack_proc_other_pss = |
181 (memtrack_proc_other_pss_t)dlsym(libhandle, "memtrack_proc_other_pss"); | 180 (memtrack_proc_other_pss_t)dlsym(libhandle, "memtrack_proc_other_pss"); |
182 | 181 |
183 if (!memtrack_init || !memtrack_proc_new || !memtrack_proc_destroy || | 182 if (!memtrack_proc_new || !memtrack_proc_destroy || !memtrack_proc_get) { |
184 !memtrack_proc_get) { | |
185 exit_with_failure("dlsym() libmemtrack.so"); | 183 exit_with_failure("dlsym() libmemtrack.so"); |
186 } | 184 } |
187 | 185 |
188 const int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); | 186 const int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); |
189 if (server_fd < 0) | 187 if (server_fd < 0) |
190 exit_with_failure("socket"); | 188 exit_with_failure("socket"); |
191 | 189 |
192 /* Initialize the socket */ | 190 /* Initialize the socket */ |
193 struct sockaddr_un server_addr; | 191 struct sockaddr_un server_addr; |
194 init_memtrack_server_addr(&server_addr); | 192 init_memtrack_server_addr(&server_addr); |
195 | 193 |
196 /* Shutdown previously running instances if any. */ | 194 /* Shutdown previously running instances if any. */ |
197 int i; | 195 int i; |
198 for (i = 0; i < 3; ++i) { | 196 for (i = 0; i < 3; ++i) { |
199 res = bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); | 197 res = bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); |
200 if (res && errno == EADDRINUSE) { | 198 if (res && errno == EADDRINUSE) { |
201 send_shutdown_request(&server_addr); | 199 send_shutdown_request(&server_addr); |
202 usleep(250000); | 200 usleep(250000); |
203 continue; | 201 continue; |
204 } | 202 } |
205 break; | 203 break; |
206 } | 204 } |
207 | 205 |
208 if (res) | 206 if (res) |
209 exit_with_failure("bind"); | 207 exit_with_failure("bind"); |
210 | 208 |
211 if (argc > 1 && strcmp(argv[1], "-d") == 0) | 209 if (argc > 1 && strcmp(argv[1], "-d") == 0) |
212 daemonize(); | 210 daemonize(); |
213 | 211 |
214 res = memtrack_init(); | 212 long pid = getpid(); |
215 if (res == -ENOENT) { | 213 fprintf(stderr, "pid=%ld\n", pid); |
216 exit_with_failure("Unable to load memtrack module in libhardware. " | 214 __android_log_print(ANDROID_LOG_INFO, kLogTag, "pid=%ld\n", pid); |
217 "Probably implementation is missing in this ROM."); | 215 |
218 } else if (res != 0) { | 216 if (memtrack_init) { |
219 exit_with_failure("memtrack_init() returned non-zero status."); | 217 res = memtrack_init(); |
| 218 if (res == -ENOENT) { |
| 219 exit_with_failure("Unable to load memtrack module in libhardware. " |
| 220 "Probably implementation is missing in this ROM."); |
| 221 } else if (res != 0) { |
| 222 exit_with_failure("memtrack_init() returned non-zero status."); |
| 223 } |
220 } | 224 } |
221 | 225 |
222 if (listen(server_fd, 128 /* max number of queued requests */)) | 226 if (listen(server_fd, 128 /* max number of queued requests */)) |
223 exit_with_failure("listen"); | 227 exit_with_failure("listen"); |
224 | 228 |
225 for (;;) { | 229 for (;;) { |
226 struct sockaddr_un client_addr; | 230 struct sockaddr_un client_addr; |
227 socklen_t len = sizeof(client_addr); | 231 socklen_t len = sizeof(client_addr); |
228 int client_sock = accept(server_fd, (struct sockaddr*)&client_addr, &len); | 232 int client_sock = accept(server_fd, (struct sockaddr*)&client_addr, &len); |
229 handle_one_request(client_sock); | 233 handle_one_request(client_sock); |
230 close(client_sock); | 234 close(client_sock); |
231 } | 235 } |
232 | 236 |
233 return EXIT_SUCCESS; | 237 return EXIT_SUCCESS; |
234 } | 238 } |
OLD | NEW |