Chromium Code Reviews| 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> | |
| 12 #include <signal.h> | |
| 13 #include <stdio.h> | 11 #include <stdio.h> |
| 14 #include <stdlib.h> | 12 #include <stdlib.h> |
| 15 #include <string.h> | 13 #include <string.h> |
| 16 #include <unistd.h> | |
| 17 #include <sys/socket.h> | 14 #include <sys/socket.h> |
| 18 #include <sys/un.h> | 15 #include <sys/un.h> |
| 19 #include <sys/stat.h> | 16 #include <sys/stat.h> |
| 20 #include <sys/types.h> | 17 #include <sys/types.h> |
| 21 #include <sys/wait.h> | |
| 22 | 18 |
| 23 /* | 19 /* |
| 24 * This is a helper daemon for Android which makes memtrack graphics information | 20 * 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. | 21 * accessible via a UNIX socket. It is used by telemetry and memory-infra. |
| 26 * More description in the design-doc: https://goo.gl/4Y30p9 . | 22 * More description in the design-doc: https://goo.gl/4Y30p9 . |
| 27 */ | 23 */ |
| 28 | 24 |
| 29 static const char kShutdownRequest = 'Q'; | 25 static const char kShutdownRequest = 'Q'; |
| 30 | 26 |
| 31 // See $ANDROID/system/core/include/memtrack/memtrack.h. | 27 // See $ANDROID/system/core/include/memtrack/memtrack.h. |
| 32 typedef void* memtrack_proc_handle; | 28 struct memtrack_proc; |
|
Primiano Tucci (use gerrit)
2016/12/14 15:51:16
why this? we don't care what's the real type of th
kraynov
2016/12/15 15:43:47
Done.
| |
| 29 typedef struct memtrack_proc* memtrack_proc_handle; | |
| 33 typedef int (*memtrack_init_t)(void); | 30 typedef int (*memtrack_init_t)(void); |
| 34 typedef memtrack_proc_handle (*memtrack_proc_new_t)(void); | 31 typedef memtrack_proc_handle (*memtrack_proc_new_t)(void); |
| 35 typedef void (*memtrack_proc_destroy_t)(memtrack_proc_handle); | 32 typedef void (*memtrack_proc_destroy_t)(memtrack_proc_handle); |
| 36 typedef int (*memtrack_proc_get_t)(memtrack_proc_handle, pid_t); | 33 typedef int (*memtrack_proc_get_t)(memtrack_proc_handle, pid_t); |
| 37 typedef ssize_t (*memtrack_proc_graphics_total_t)(memtrack_proc_handle); | 34 typedef ssize_t (*memtrack_proc_graphics_total_t)(memtrack_proc_handle); |
| 38 typedef ssize_t (*memtrack_proc_graphics_pss_t)(memtrack_proc_handle); | 35 typedef ssize_t (*memtrack_proc_graphics_pss_t)(memtrack_proc_handle); |
| 39 typedef ssize_t (*memtrack_proc_gl_total_t)(memtrack_proc_handle); | 36 typedef ssize_t (*memtrack_proc_gl_total_t)(memtrack_proc_handle); |
| 40 typedef ssize_t (*memtrack_proc_gl_pss_t)(memtrack_proc_handle); | 37 typedef ssize_t (*memtrack_proc_gl_pss_t)(memtrack_proc_handle); |
| 41 typedef ssize_t (*memtrack_proc_other_total_t)(memtrack_proc_handle); | 38 typedef ssize_t (*memtrack_proc_other_total_t)(memtrack_proc_handle); |
| 42 typedef ssize_t (*memtrack_proc_other_pss_t)(memtrack_proc_handle); | 39 typedef ssize_t (*memtrack_proc_other_pss_t)(memtrack_proc_handle); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 59 static void send_shutdown_request(struct sockaddr_un* addr) { | 56 static void send_shutdown_request(struct sockaddr_un* addr) { |
| 60 int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); | 57 int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); |
| 61 connect(sock, (struct sockaddr*)addr, sizeof(*addr)); | 58 connect(sock, (struct sockaddr*)addr, sizeof(*addr)); |
| 62 send(sock, &kShutdownRequest, 1, 0); | 59 send(sock, &kShutdownRequest, 1, 0); |
| 63 close(sock); | 60 close(sock); |
| 64 } | 61 } |
| 65 | 62 |
| 66 static void handle_one_request(int client_sock) { | 63 static void handle_one_request(int client_sock) { |
| 67 char buf[32]; | 64 char buf[32]; |
| 68 char response[4096] = ""; | 65 char response[4096] = ""; |
| 69 ssize_t rsize = recv(client_sock, buf, sizeof(buf), 0); | 66 ssize_t rsize = recv(client_sock, buf, sizeof(buf) - 1, 0); |
| 67 buf[rsize] = '\0'; | |
|
Primiano Tucci (use gerrit)
2016/12/14 15:51:16
now this will crash if recv fails and rsize = -1
I
kraynov
2016/12/15 15:43:48
Done.
| |
| 70 | 68 |
| 71 if (rsize < 1) | 69 if (rsize < 1) |
| 72 return; | 70 return; |
| 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() { | |
| 121 pid_t pid; | |
| 122 | |
| 123 pid = fork(); | |
| 124 if (pid < 0) | |
| 125 exit_with_failure("fork"); | |
| 126 if (pid > 0) { | |
| 127 /* Terminate the main process attached to TTY once the daemon re-forks. */ | |
| 128 int ignore; | |
| 129 wait(&ignore); | |
| 130 exit(EXIT_SUCCESS); | |
| 131 } | |
| 132 | |
| 133 if (setsid() == -1) | |
| 134 exit_with_failure("setsid"); | |
| 135 | |
| 136 chdir("/"); | |
| 137 umask(0); | |
| 138 close(STDIN_FILENO); | |
| 139 close(STDOUT_FILENO); | |
| 140 close(STDERR_FILENO); | |
| 141 open("/dev/null", O_RDONLY); | |
| 142 open("/dev/null", O_WRONLY); | |
| 143 open("/dev/null", O_RDWR); | |
| 144 | |
| 145 pid = fork(); | |
| 146 if (pid < 0) | |
| 147 exit_with_failure("fork"); | |
| 148 if (pid > 0) | |
| 149 exit(EXIT_SUCCESS); | |
| 150 } | |
| 151 | |
| 152 int main(int argc, char** argv) { | 118 int main(int argc, char** argv) { |
| 153 int res; | 119 int res; |
| 154 | 120 |
| 155 if (getuid() != 0) { | 121 if (getuid() != 0) { |
| 156 fprintf(stderr, "FATAL: %s must be run as root!\n", argv[0]); | 122 fprintf(stderr, "FATAL: %s must be run as root!\n", argv[0]); |
| 157 return EXIT_FAILURE; | 123 return EXIT_FAILURE; |
| 158 } | 124 } |
| 159 | 125 |
| 160 void* const libhandle = dlopen("libmemtrack.so", RTLD_GLOBAL | RTLD_NOW); | 126 void* const libhandle = dlopen("libmemtrack.so", RTLD_GLOBAL | RTLD_NOW); |
| 161 if (!libhandle) | 127 if (!libhandle) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 173 libhandle, "memtrack_proc_graphics_pss"); | 139 libhandle, "memtrack_proc_graphics_pss"); |
| 174 memtrack_proc_gl_total = | 140 memtrack_proc_gl_total = |
| 175 (memtrack_proc_gl_total_t)dlsym(libhandle, "memtrack_proc_gl_total"); | 141 (memtrack_proc_gl_total_t)dlsym(libhandle, "memtrack_proc_gl_total"); |
| 176 memtrack_proc_gl_pss = | 142 memtrack_proc_gl_pss = |
| 177 (memtrack_proc_gl_pss_t)dlsym(libhandle, "memtrack_proc_gl_pss"); | 143 (memtrack_proc_gl_pss_t)dlsym(libhandle, "memtrack_proc_gl_pss"); |
| 178 memtrack_proc_other_total = (memtrack_proc_other_total_t)dlsym( | 144 memtrack_proc_other_total = (memtrack_proc_other_total_t)dlsym( |
| 179 libhandle, "memtrack_proc_other_total"); | 145 libhandle, "memtrack_proc_other_total"); |
| 180 memtrack_proc_other_pss = | 146 memtrack_proc_other_pss = |
| 181 (memtrack_proc_other_pss_t)dlsym(libhandle, "memtrack_proc_other_pss"); | 147 (memtrack_proc_other_pss_t)dlsym(libhandle, "memtrack_proc_other_pss"); |
| 182 | 148 |
| 183 if (!memtrack_init || !memtrack_proc_new || !memtrack_proc_destroy || | 149 if (!memtrack_proc_new || !memtrack_proc_destroy || !memtrack_proc_get) { |
| 184 !memtrack_proc_get) { | |
| 185 exit_with_failure("dlsym() libmemtrack.so"); | 150 exit_with_failure("dlsym() libmemtrack.so"); |
| 186 } | 151 } |
| 187 | 152 |
| 188 const int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); | 153 const int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); |
| 189 if (server_fd < 0) | 154 if (server_fd < 0) |
| 190 exit_with_failure("socket"); | 155 exit_with_failure("socket"); |
| 191 | 156 |
| 192 /* Initialize the socket */ | 157 /* Initialize the socket */ |
| 193 struct sockaddr_un server_addr; | 158 struct sockaddr_un server_addr; |
| 194 init_memtrack_server_addr(&server_addr); | 159 init_memtrack_server_addr(&server_addr); |
| 195 | 160 |
| 196 /* Shutdown previously running instances if any. */ | 161 /* Shutdown previously running instances if any. */ |
| 197 int i; | 162 int i; |
| 198 for (i = 0; i < 3; ++i) { | 163 for (i = 0; i < 3; ++i) { |
| 199 res = bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); | 164 res = bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); |
| 200 if (res && errno == EADDRINUSE) { | 165 if (res && errno == EADDRINUSE) { |
| 201 send_shutdown_request(&server_addr); | 166 send_shutdown_request(&server_addr); |
| 202 usleep(250000); | 167 usleep(250000); |
| 203 continue; | 168 continue; |
| 204 } | 169 } |
| 205 break; | 170 break; |
| 206 } | 171 } |
| 207 | 172 |
| 208 if (res) | 173 if (res) |
| 209 exit_with_failure("bind"); | 174 exit_with_failure("bind"); |
| 210 | 175 |
| 211 if (argc > 1 && strcmp(argv[1], "-d") == 0) | 176 if (argc > 1 && strcmp(argv[1], "-d") == 0) { |
| 212 daemonize(); | 177 int res = daemon(0, 0); |
| 178 if (res != 0) | |
| 179 exit_with_failure("Failed to daemonize."); | |
| 180 } | |
| 181 log_pid(); | |
| 213 | 182 |
| 214 res = memtrack_init(); | 183 if (memtrack_init) { |
| 215 if (res == -ENOENT) { | 184 res = memtrack_init(); |
| 216 exit_with_failure("Unable to load memtrack module in libhardware. " | 185 if (res == -ENOENT) { |
| 217 "Probably implementation is missing in this ROM."); | 186 exit_with_failure("Unable to load memtrack module in libhardware. " |
| 218 } else if (res != 0) { | 187 "Probably implementation is missing in this ROM."); |
| 219 exit_with_failure("memtrack_init() returned non-zero status."); | 188 } else if (res != 0) { |
| 189 exit_with_failure("memtrack_init() returned non-zero status."); | |
| 190 } | |
| 191 } else { | |
| 192 // memtrack_init() has been removed in newer versions of libmemtrack and | |
| 193 // replaced with lazy initialization. This code triggers that. | |
| 194 memtrack_proc_handle handle = memtrack_proc_new(); | |
| 195 if (!handle) | |
| 196 exit_with_failure("memtrack_proc_new() failed."); | |
| 197 if (memtrack_proc_get(handle, getpid()) != 0) | |
|
Primiano Tucci (use gerrit)
2016/12/14 15:51:16
Hmm I'd remove this. Since this is a non-(Java)-ma
kraynov
2016/12/15 15:43:47
Acknowledged.
| |
| 198 exit_with_failure("memtrack_proc_get() returned non-zero status."); | |
| 199 memtrack_proc_destroy(handle); | |
| 220 } | 200 } |
| 221 | 201 |
| 222 if (listen(server_fd, 128 /* max number of queued requests */)) | 202 if (listen(server_fd, 128 /* max number of queued requests */)) |
| 223 exit_with_failure("listen"); | 203 exit_with_failure("listen"); |
| 224 | 204 |
| 225 for (;;) { | 205 for (;;) { |
| 226 struct sockaddr_un client_addr; | 206 struct sockaddr_un client_addr; |
| 227 socklen_t len = sizeof(client_addr); | 207 socklen_t len = sizeof(client_addr); |
| 228 int client_sock = accept(server_fd, (struct sockaddr*)&client_addr, &len); | 208 int client_sock = accept(server_fd, (struct sockaddr*)&client_addr, &len); |
| 229 handle_one_request(client_sock); | 209 handle_one_request(client_sock); |
| 230 close(client_sock); | 210 close(client_sock); |
| 231 } | 211 } |
| 232 | 212 |
| 233 return EXIT_SUCCESS; | 213 return EXIT_SUCCESS; |
| 234 } | 214 } |
| OLD | NEW |