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