Home | History | Annotate | Download | only in dumpstate
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    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  */
    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  */
    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 
    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 */
    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 
    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 
    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 */
    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 */
    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 */
    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 
    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) */
    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 
    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