• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 <dirent.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <limits.h>
21 #include <poll.h>
22 #include <signal.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/inotify.h>
28 #include <sys/stat.h>
29 #include <sys/time.h>
30 #include <sys/wait.h>
31 #include <sys/klog.h>
32 #include <time.h>
33 #include <unistd.h>
34 #include <sys/prctl.h>
35 
36 #include <cutils/debugger.h>
37 #include <cutils/properties.h>
38 #include <cutils/sockets.h>
39 #include <private/android_filesystem_config.h>
40 
41 #include <selinux/android.h>
42 
43 #include "dumpstate.h"
44 
45 static const int64_t NANOS_PER_SEC = 1000000000;
46 
47 /* list of native processes to include in the native dumps */
48 static const char* native_processes_to_dump[] = {
49         "/system/bin/drmserver",
50         "/system/bin/mediaserver",
51         "/system/bin/sdcard",
52         "/system/bin/surfaceflinger",
53         NULL,
54 };
55 
nanotime()56 static uint64_t nanotime() {
57     struct timespec ts;
58     clock_gettime(CLOCK_MONOTONIC, &ts);
59     return (uint64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec;
60 }
61 
for_each_userid(void (* func)(int),const char * header)62 void for_each_userid(void (*func)(int), const char *header) {
63     DIR *d;
64     struct dirent *de;
65 
66     if (header) printf("\n------ %s ------\n", header);
67     func(0);
68 
69     if (!(d = opendir("/data/system/users"))) {
70         printf("Failed to open /data/system/users (%s)\n", strerror(errno));
71         return;
72     }
73 
74     while ((de = readdir(d))) {
75         int userid;
76         if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
77             continue;
78         }
79         func(userid);
80     }
81 
82     closedir(d);
83 }
84 
__for_each_pid(void (* helper)(int,const char *,void *),const char * header,void * arg)85 static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
86     DIR *d;
87     struct dirent *de;
88 
89     if (!(d = opendir("/proc"))) {
90         printf("Failed to open /proc (%s)\n", strerror(errno));
91         return;
92     }
93 
94     printf("\n------ %s ------\n", header);
95     while ((de = readdir(d))) {
96         int pid;
97         int fd;
98         char cmdpath[255];
99         char cmdline[255];
100 
101         if (!(pid = atoi(de->d_name))) {
102             continue;
103         }
104 
105         sprintf(cmdpath,"/proc/%d/cmdline", pid);
106         memset(cmdline, 0, sizeof(cmdline));
107         if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) < 0) {
108             strcpy(cmdline, "N/A");
109         } else {
110             read(fd, cmdline, sizeof(cmdline) - 1);
111             close(fd);
112         }
113         helper(pid, cmdline, arg);
114     }
115 
116     closedir(d);
117 }
118 
for_each_pid_helper(int pid,const char * cmdline,void * arg)119 static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
120     for_each_pid_func *func = arg;
121     func(pid, cmdline);
122 }
123 
for_each_pid(for_each_pid_func func,const char * header)124 void for_each_pid(for_each_pid_func func, const char *header) {
125     __for_each_pid(for_each_pid_helper, header, func);
126 }
127 
for_each_tid_helper(int pid,const char * cmdline,void * arg)128 static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
129     DIR *d;
130     struct dirent *de;
131     char taskpath[255];
132     for_each_tid_func *func = arg;
133 
134     sprintf(taskpath, "/proc/%d/task", pid);
135 
136     if (!(d = opendir(taskpath))) {
137         printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
138         return;
139     }
140 
141     func(pid, pid, cmdline);
142 
143     while ((de = readdir(d))) {
144         int tid;
145         int fd;
146         char commpath[255];
147         char comm[255];
148 
149         if (!(tid = atoi(de->d_name))) {
150             continue;
151         }
152 
153         if (tid == pid)
154             continue;
155 
156         sprintf(commpath,"/proc/%d/comm", tid);
157         memset(comm, 0, sizeof(comm));
158         if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
159             strcpy(comm, "N/A");
160         } else {
161             char *c;
162             read(fd, comm, sizeof(comm) - 1);
163             close(fd);
164 
165             c = strrchr(comm, '\n');
166             if (c) {
167                 *c = '\0';
168             }
169         }
170         func(pid, tid, comm);
171     }
172 
173     closedir(d);
174 }
175 
for_each_tid(for_each_tid_func func,const char * header)176 void for_each_tid(for_each_tid_func func, const char *header) {
177     __for_each_pid(for_each_tid_helper, header, func);
178 }
179 
show_wchan(int pid,int tid,const char * name)180 void show_wchan(int pid, int tid, const char *name) {
181     char path[255];
182     char buffer[255];
183     int fd;
184     char name_buffer[255];
185 
186     memset(buffer, 0, sizeof(buffer));
187 
188     sprintf(path, "/proc/%d/wchan", tid);
189     if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
190         printf("Failed to open '%s' (%s)\n", path, strerror(errno));
191         return;
192     }
193 
194     if (read(fd, buffer, sizeof(buffer)) < 0) {
195         printf("Failed to read '%s' (%s)\n", path, strerror(errno));
196         goto out_close;
197     }
198 
199     snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
200              pid == tid ? 0 : 3, "", name);
201 
202     printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
203 
204 out_close:
205     close(fd);
206     return;
207 }
208 
do_dmesg()209 void do_dmesg() {
210     printf("------ KERNEL LOG (dmesg) ------\n");
211     /* Get size of kernel buffer */
212     int size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
213     if (size <= 0) {
214         printf("Unexpected klogctl return value: %d\n\n", size);
215         return;
216     }
217     char *buf = (char *) malloc(size + 1);
218     if (buf == NULL) {
219         printf("memory allocation failed\n\n");
220         return;
221     }
222     int retval = klogctl(KLOG_READ_ALL, buf, size);
223     if (retval < 0) {
224         printf("klogctl failure\n\n");
225         free(buf);
226         return;
227     }
228     buf[retval] = '\0';
229     printf("%s\n\n", buf);
230     free(buf);
231     return;
232 }
233 
do_showmap(int pid,const char * name)234 void do_showmap(int pid, const char *name) {
235     char title[255];
236     char arg[255];
237 
238     sprintf(title, "SHOW MAP %d (%s)", pid, name);
239     sprintf(arg, "%d", pid);
240     run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL);
241 }
242 
_dump_file_from_fd(const char * title,const char * path,int fd)243 static int _dump_file_from_fd(const char *title, const char *path, int fd) {
244     if (title) printf("------ %s (%s", title, path);
245 
246     if (title) {
247         struct stat st;
248         if (memcmp(path, "/proc/", 6) && memcmp(path, "/sys/", 5) && !fstat(fd, &st)) {
249             char stamp[80];
250             time_t mtime = st.st_mtime;
251             strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&mtime));
252             printf(": %s", stamp);
253         }
254         printf(") ------\n");
255     }
256 
257     bool newline = false;
258     fd_set read_set;
259     struct timeval tm;
260     while (1) {
261         FD_ZERO(&read_set);
262         FD_SET(fd, &read_set);
263         /* Timeout if no data is read for 30 seconds. */
264         tm.tv_sec = 30;
265         tm.tv_usec = 0;
266         uint64_t elapsed = nanotime();
267         int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm));
268         if (ret == -1) {
269             printf("*** %s: select failed: %s\n", path, strerror(errno));
270             newline = true;
271             break;
272         } else if (ret == 0) {
273             elapsed = nanotime() - elapsed;
274             printf("*** %s: Timed out after %.3fs\n", path,
275                    (float) elapsed / NANOS_PER_SEC);
276             newline = true;
277             break;
278         } else {
279             char buffer[65536];
280             ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
281             if (bytes_read > 0) {
282                 fwrite(buffer, bytes_read, 1, stdout);
283                 newline = (buffer[bytes_read-1] == '\n');
284             } else {
285                 if (bytes_read == -1) {
286                     printf("*** %s: Failed to read from fd: %s", path, strerror(errno));
287                     newline = true;
288                 }
289                 break;
290             }
291         }
292     }
293     close(fd);
294 
295     if (!newline) printf("\n");
296     if (title) printf("\n");
297     return 0;
298 }
299 
300 /* prints the contents of a file */
dump_file(const char * title,const char * path)301 int dump_file(const char *title, const char *path) {
302     int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
303     if (fd < 0) {
304         int err = errno;
305         if (title) printf("------ %s (%s) ------\n", title, path);
306         printf("*** %s: %s\n", path, strerror(err));
307         if (title) printf("\n");
308         return -1;
309     }
310     return _dump_file_from_fd(title, path, fd);
311 }
312 
313 /* calls skip to gate calling dump_from_fd recursively
314  * in the specified directory. dump_from_fd defaults to
315  * dump_file_from_fd above when set to NULL. skip defaults
316  * to false when set to NULL. dump_from_fd will always be
317  * called with title NULL.
318  */
dump_files(const char * title,const char * dir,bool (* skip)(const char * path),int (* dump_from_fd)(const char * title,const char * path,int fd))319 int dump_files(const char *title, const char *dir,
320         bool (*skip)(const char *path),
321         int (*dump_from_fd)(const char *title, const char *path, int fd)) {
322     DIR *dirp;
323     struct dirent *d;
324     char *newpath = NULL;
325     char *slash = "/";
326     int fd, retval = 0;
327 
328     if (title) {
329         printf("------ %s (%s) ------\n", title, dir);
330     }
331 
332     if (dir[strlen(dir) - 1] == '/') {
333         ++slash;
334     }
335     dirp = opendir(dir);
336     if (dirp == NULL) {
337         retval = -errno;
338         fprintf(stderr, "%s: %s\n", dir, strerror(errno));
339         return retval;
340     }
341 
342     if (!dump_from_fd) {
343         dump_from_fd = dump_file_from_fd;
344     }
345     for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) {
346         if ((d->d_name[0] == '.')
347          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
348           || (d->d_name[1] == '\0'))) {
349             continue;
350         }
351         asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
352                  (d->d_type == DT_DIR) ? "/" : "");
353         if (!newpath) {
354             retval = -errno;
355             continue;
356         }
357         if (skip && (*skip)(newpath)) {
358             continue;
359         }
360         if (d->d_type == DT_DIR) {
361             int ret = dump_files(NULL, newpath, skip, dump_from_fd);
362             if (ret < 0) {
363                 retval = ret;
364             }
365             continue;
366         }
367         fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
368         if (fd < 0) {
369             retval = fd;
370             printf("*** %s: %s\n", newpath, strerror(errno));
371             continue;
372         }
373         (*dump_from_fd)(NULL, newpath, fd);
374     }
375     closedir(dirp);
376     if (title) {
377         printf("\n");
378     }
379     return retval;
380 }
381 
382 /* fd must have been opened with the flag O_NONBLOCK. With this flag set,
383  * it's possible to avoid issues where opening the file itself can get
384  * stuck.
385  */
dump_file_from_fd(const char * title,const char * path,int fd)386 int dump_file_from_fd(const char *title, const char *path, int fd) {
387     int flags = fcntl(fd, F_GETFL);
388     if (flags == -1) {
389         printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
390         return -1;
391     } else if (!(flags & O_NONBLOCK)) {
392         printf("*** %s: fd must have O_NONBLOCK set.\n", path);
393         return -1;
394     }
395     return _dump_file_from_fd(title, path, fd);
396 }
397 
waitpid_with_timeout(pid_t pid,int timeout_seconds,int * status)398 bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
399     sigset_t child_mask, old_mask;
400     sigemptyset(&child_mask);
401     sigaddset(&child_mask, SIGCHLD);
402 
403     if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
404         printf("*** sigprocmask failed: %s\n", strerror(errno));
405         return false;
406     }
407 
408     struct timespec ts;
409     ts.tv_sec = timeout_seconds;
410     ts.tv_nsec = 0;
411     int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
412     int saved_errno = errno;
413     // Set the signals back the way they were.
414     if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
415         printf("*** sigprocmask failed: %s\n", strerror(errno));
416         if (ret == 0) {
417             return false;
418         }
419     }
420     if (ret == -1) {
421         errno = saved_errno;
422         if (errno == EAGAIN) {
423             errno = ETIMEDOUT;
424         } else {
425             printf("*** sigtimedwait failed: %s\n", strerror(errno));
426         }
427         return false;
428     }
429 
430     pid_t child_pid = waitpid(pid, status, WNOHANG);
431     if (child_pid != pid) {
432         if (child_pid != -1) {
433             printf("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid);
434         } else {
435             printf("*** waitpid failed: %s\n", strerror(errno));
436         }
437         return false;
438     }
439     return true;
440 }
441 
442 /* forks a command and waits for it to finish */
run_command(const char * title,int timeout_seconds,const char * command,...)443 int run_command(const char *title, int timeout_seconds, const char *command, ...) {
444     fflush(stdout);
445     uint64_t start = nanotime();
446     pid_t pid = fork();
447 
448     /* handle error case */
449     if (pid < 0) {
450         printf("*** fork: %s\n", strerror(errno));
451         return pid;
452     }
453 
454     /* handle child case */
455     if (pid == 0) {
456         const char *args[1024] = {command};
457         size_t arg;
458 
459         /* make sure the child dies when dumpstate dies */
460         prctl(PR_SET_PDEATHSIG, SIGKILL);
461 
462         /* just ignore SIGPIPE, will go down with parent's */
463         struct sigaction sigact;
464         memset(&sigact, 0, sizeof(sigact));
465         sigact.sa_handler = SIG_IGN;
466         sigaction(SIGPIPE, &sigact, NULL);
467 
468         va_list ap;
469         va_start(ap, command);
470         if (title) printf("------ %s (%s", title, command);
471         for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
472             args[arg] = va_arg(ap, const char *);
473             if (args[arg] == NULL) break;
474             if (title) printf(" %s", args[arg]);
475         }
476         if (title) printf(") ------\n");
477         fflush(stdout);
478 
479         execvp(command, (char**) args);
480         printf("*** exec(%s): %s\n", command, strerror(errno));
481         fflush(stdout);
482         _exit(-1);
483     }
484 
485     /* handle parent case */
486     int status;
487     bool ret = waitpid_with_timeout(pid, timeout_seconds, &status);
488     uint64_t elapsed = nanotime() - start;
489     if (!ret) {
490         if (errno == ETIMEDOUT) {
491             printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command,
492                    (float) elapsed / NANOS_PER_SEC, pid);
493         } else {
494             printf("*** %s: Error after %.4fs (killing pid %d)\n", command,
495                    (float) elapsed / NANOS_PER_SEC, pid);
496         }
497         kill(pid, SIGTERM);
498         if (!waitpid_with_timeout(pid, 5, NULL)) {
499             kill(pid, SIGKILL);
500             if (!waitpid_with_timeout(pid, 5, NULL)) {
501                 printf("*** %s: Cannot kill %d even with SIGKILL.\n", command, pid);
502             }
503         }
504         return -1;
505     }
506 
507     if (WIFSIGNALED(status)) {
508         printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
509     } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
510         printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
511     }
512     if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC);
513 
514     return status;
515 }
516 
517 size_t num_props = 0;
518 static char* props[2000];
519 
print_prop(const char * key,const char * name,void * user)520 static void print_prop(const char *key, const char *name, void *user) {
521     (void) user;
522     if (num_props < sizeof(props) / sizeof(props[0])) {
523         char buf[PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 10];
524         snprintf(buf, sizeof(buf), "[%s]: [%s]\n", key, name);
525         props[num_props++] = strdup(buf);
526     }
527 }
528 
compare_prop(const void * a,const void * b)529 static int compare_prop(const void *a, const void *b) {
530     return strcmp(*(char * const *) a, *(char * const *) b);
531 }
532 
533 /* prints all the system properties */
print_properties()534 void print_properties() {
535     size_t i;
536     num_props = 0;
537     property_list(print_prop, NULL);
538     qsort(&props, num_props, sizeof(props[0]), compare_prop);
539 
540     printf("------ SYSTEM PROPERTIES ------\n");
541     for (i = 0; i < num_props; ++i) {
542         fputs(props[i], stdout);
543         free(props[i]);
544     }
545     printf("\n");
546 }
547 
548 /* redirect output to a service control socket */
redirect_to_socket(FILE * redirect,const char * service)549 void redirect_to_socket(FILE *redirect, const char *service) {
550     int s = android_get_control_socket(service);
551     if (s < 0) {
552         fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno));
553         exit(1);
554     }
555     fcntl(s, F_SETFD, FD_CLOEXEC);
556     if (listen(s, 4) < 0) {
557         fprintf(stderr, "listen(control socket): %s\n", strerror(errno));
558         exit(1);
559     }
560 
561     struct sockaddr addr;
562     socklen_t alen = sizeof(addr);
563     int fd = accept(s, &addr, &alen);
564     if (fd < 0) {
565         fprintf(stderr, "accept(control socket): %s\n", strerror(errno));
566         exit(1);
567     }
568 
569     fflush(redirect);
570     dup2(fd, fileno(redirect));
571     close(fd);
572 }
573 
574 /* redirect output to a file */
redirect_to_file(FILE * redirect,char * path)575 void redirect_to_file(FILE *redirect, char *path) {
576     char *chp = path;
577 
578     /* skip initial slash */
579     if (chp[0] == '/')
580         chp++;
581 
582     /* create leading directories, if necessary */
583     while (chp && chp[0]) {
584         chp = strchr(chp, '/');
585         if (chp) {
586             *chp = 0;
587             mkdir(path, 0770);  /* drwxrwx--- */
588             *chp++ = '/';
589         }
590     }
591 
592     int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
593                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
594     if (fd < 0) {
595         fprintf(stderr, "%s: %s\n", path, strerror(errno));
596         exit(1);
597     }
598 
599     TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
600     close(fd);
601 }
602 
should_dump_native_traces(const char * path)603 static bool should_dump_native_traces(const char* path) {
604     for (const char** p = native_processes_to_dump; *p; p++) {
605         if (!strcmp(*p, path)) {
606             return true;
607         }
608     }
609     return false;
610 }
611 
612 /* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
dump_traces()613 const char *dump_traces() {
614     const char* result = NULL;
615 
616     char traces_path[PROPERTY_VALUE_MAX] = "";
617     property_get("dalvik.vm.stack-trace-file", traces_path, "");
618     if (!traces_path[0]) return NULL;
619 
620     /* move the old traces.txt (if any) out of the way temporarily */
621     char anr_traces_path[PATH_MAX];
622     strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
623     strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
624     if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
625         fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
626         return NULL;  // Can't rename old traces.txt -- no permission? -- leave it alone instead
627     }
628 
629     /* make the directory if necessary */
630     char anr_traces_dir[PATH_MAX];
631     strlcpy(anr_traces_dir, traces_path, sizeof(anr_traces_dir));
632     char *slash = strrchr(anr_traces_dir, '/');
633     if (slash != NULL) {
634         *slash = '\0';
635         if (!mkdir(anr_traces_dir, 0775)) {
636             chown(anr_traces_dir, AID_SYSTEM, AID_SYSTEM);
637             chmod(anr_traces_dir, 0775);
638             if (selinux_android_restorecon(anr_traces_dir, 0) == -1) {
639                 fprintf(stderr, "restorecon failed for %s: %s\n", anr_traces_dir, strerror(errno));
640             }
641         } else if (errno != EEXIST) {
642             fprintf(stderr, "mkdir(%s): %s\n", anr_traces_dir, strerror(errno));
643             return NULL;
644         }
645     }
646 
647     /* create a new, empty traces.txt file to receive stack dumps */
648     int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
649                                      0666));  /* -rw-rw-rw- */
650     if (fd < 0) {
651         fprintf(stderr, "%s: %s\n", traces_path, strerror(errno));
652         return NULL;
653     }
654     int chmod_ret = fchmod(fd, 0666);
655     if (chmod_ret < 0) {
656         fprintf(stderr, "fchmod on %s failed: %s\n", traces_path, strerror(errno));
657         close(fd);
658         return NULL;
659     }
660 
661     /* walk /proc and kill -QUIT all Dalvik processes */
662     DIR *proc = opendir("/proc");
663     if (proc == NULL) {
664         fprintf(stderr, "/proc: %s\n", strerror(errno));
665         goto error_close_fd;
666     }
667 
668     /* use inotify to find when processes are done dumping */
669     int ifd = inotify_init();
670     if (ifd < 0) {
671         fprintf(stderr, "inotify_init: %s\n", strerror(errno));
672         goto error_close_fd;
673     }
674 
675     int wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE);
676     if (wfd < 0) {
677         fprintf(stderr, "inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
678         goto error_close_ifd;
679     }
680 
681     struct dirent *d;
682     int dalvik_found = 0;
683     while ((d = readdir(proc))) {
684         int pid = atoi(d->d_name);
685         if (pid <= 0) continue;
686 
687         char path[PATH_MAX];
688         char data[PATH_MAX];
689         snprintf(path, sizeof(path), "/proc/%d/exe", pid);
690         ssize_t len = readlink(path, data, sizeof(data) - 1);
691         if (len <= 0) {
692             continue;
693         }
694         data[len] = '\0';
695 
696         if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) {
697             /* skip zygote -- it won't dump its stack anyway */
698             snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
699             int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
700             len = read(cfd, data, sizeof(data) - 1);
701             close(cfd);
702             if (len <= 0) {
703                 continue;
704             }
705             data[len] = '\0';
706             if (!strncmp(data, "zygote", strlen("zygote"))) {
707                 continue;
708             }
709 
710             ++dalvik_found;
711             uint64_t start = nanotime();
712             if (kill(pid, SIGQUIT)) {
713                 fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
714                 continue;
715             }
716 
717             /* wait for the writable-close notification from inotify */
718             struct pollfd pfd = { ifd, POLLIN, 0 };
719             int ret = poll(&pfd, 1, 5000);  /* 5 sec timeout */
720             if (ret < 0) {
721                 fprintf(stderr, "poll: %s\n", strerror(errno));
722             } else if (ret == 0) {
723                 fprintf(stderr, "warning: timed out dumping pid %d\n", pid);
724             } else {
725                 struct inotify_event ie;
726                 read(ifd, &ie, sizeof(ie));
727             }
728 
729             if (lseek(fd, 0, SEEK_END) < 0) {
730                 fprintf(stderr, "lseek: %s\n", strerror(errno));
731             } else {
732                 dprintf(fd, "[dump dalvik stack %d: %.3fs elapsed]\n",
733                         pid, (float)(nanotime() - start) / NANOS_PER_SEC);
734             }
735         } else if (should_dump_native_traces(data)) {
736             /* dump native process if appropriate */
737             if (lseek(fd, 0, SEEK_END) < 0) {
738                 fprintf(stderr, "lseek: %s\n", strerror(errno));
739             } else {
740                 static uint16_t timeout_failures = 0;
741                 uint64_t start = nanotime();
742 
743                 /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
744                 if (timeout_failures == 3) {
745                     dprintf(fd, "too many stack dump failures, skipping...\n");
746                 } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) {
747                     dprintf(fd, "dumping failed, likely due to a timeout\n");
748                     timeout_failures++;
749                 } else {
750                     timeout_failures = 0;
751                 }
752                 dprintf(fd, "[dump native stack %d: %.3fs elapsed]\n",
753                         pid, (float)(nanotime() - start) / NANOS_PER_SEC);
754             }
755         }
756     }
757 
758     if (dalvik_found == 0) {
759         fprintf(stderr, "Warning: no Dalvik processes found to dump stacks\n");
760     }
761 
762     static char dump_traces_path[PATH_MAX];
763     strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path));
764     strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path));
765     if (rename(traces_path, dump_traces_path)) {
766         fprintf(stderr, "rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
767         goto error_close_ifd;
768     }
769     result = dump_traces_path;
770 
771     /* replace the saved [ANR] traces.txt file */
772     rename(anr_traces_path, traces_path);
773 
774 error_close_ifd:
775     close(ifd);
776 error_close_fd:
777     close(fd);
778     return result;
779 }
780 
dump_route_tables()781 void dump_route_tables() {
782     const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
783     dump_file("RT_TABLES", RT_TABLES_PATH);
784     FILE* fp = fopen(RT_TABLES_PATH, "re");
785     if (!fp) {
786         printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
787         return;
788     }
789     char table[16];
790     // Each line has an integer (the table number), a space, and a string (the table name). We only
791     // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
792     // Add a fixed max limit so this doesn't go awry.
793     for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
794         run_command("ROUTE TABLE IPv4", 10, "ip", "-4", "route", "show", "table", table, NULL);
795         run_command("ROUTE TABLE IPv6", 10, "ip", "-6", "route", "show", "table", table, NULL);
796     }
797     fclose(fp);
798 }
799