19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <dirent.h>
1852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <errno.h>
1952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <fcntl.h>
2052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <limits.h>
2152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <poll.h>
2252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <signal.h>
2352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <stdarg.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
2752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <sys/inotify.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/wait.h>
3152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <time.h>
3252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <unistd.h>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/properties.h>
3552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <cutils/sockets.h>
36efd13938013099e58f4dcbf818f508c585547817Dan Egnor#include <private/android_filesystem_config.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "dumpstate.h"
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4057fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehatvoid for_each_pid(void (*func)(int, const char *), const char *header) {
4157fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    DIR *d;
4257fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    struct dirent *de;
4357fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
4457fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    if (!(d = opendir("/proc"))) {
4557fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        printf("Failed to open /proc (%s)\n", strerror(errno));
4657fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        return;
4757fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    }
4857fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
4957fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    printf("\n------ %s ------\n", header);
5057fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    while ((de = readdir(d))) {
5157fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        int pid;
5257fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        int fd;
5357fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        char cmdpath[255];
5457fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        char cmdline[255];
5557fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
5657fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        if (!(pid = atoi(de->d_name))) {
5757fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat            continue;
5857fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        }
5957fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
6057fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        sprintf(cmdpath,"/proc/%d/cmdline", pid);
6157fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        memset(cmdline, 0, sizeof(cmdline));
6257fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        if ((fd = open(cmdpath, O_RDONLY)) < 0) {
6357fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat            strcpy(cmdline, "N/A");
6457fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        } else {
6557fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat            read(fd, cmdline, sizeof(cmdline));
6657fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat            close(fd);
6757fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        }
6857fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        func(pid, cmdline);
6957fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    }
7057fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
7157fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    closedir(d);
7257fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat}
7357fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
7457fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehatvoid show_wchan(int pid, const char *name) {
7557fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    char path[255];
7657fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    char buffer[255];
7757fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    int fd;
7857fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
7957fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    memset(buffer, 0, sizeof(buffer));
8057fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
8157fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    sprintf(path, "/proc/%d/wchan", pid);
8257fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    if ((fd = open(path, O_RDONLY)) < 0) {
8357fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
8457fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        return;
8557fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    }
8657fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
8757fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    if (read(fd, buffer, sizeof(buffer)) < 0) {
8857fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        printf("Failed to read '%s' (%s)\n", path, strerror(errno));
8957fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat        goto out_close;
9057fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    }
9157fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
9257fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    printf("%-7d %-32s %s\n", pid, name, buffer);
9357fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat
9457fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehatout_close:
9557fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    close(fd);
9657fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat    return;
9757fff78a70c82ca09beb91c4f92d97b6f0b897e4San Mehat}
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* prints the contents of a file */
10052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorint dump_file(const char *title, const char* path) {
10152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    char buffer[32768];
10252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int fd = open(path, O_RDONLY);
10352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (fd < 0) {
10452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        int err = errno;
105ea11654e684cb91252487f697c72e76da507f7beDan Egnor        if (title) printf("------ %s (%s) ------\n", title, path);
10652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        printf("*** %s: %s\n", path, strerror(err));
10752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (title) printf("\n");
10852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        return -1;
10952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
111ea11654e684cb91252487f697c72e76da507f7beDan Egnor    if (title) printf("------ %s (%s", title, path);
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (title) {
11452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        struct stat st;
11552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (memcmp(path, "/proc/", 6) && memcmp(path, "/sys/", 5) && !fstat(fd, &st)) {
11652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            char stamp[80];
11752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            time_t mtime = st.st_mtime;
11852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&mtime));
11952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            printf(": %s", stamp);
12052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
121ea11654e684cb91252487f697c72e76da507f7beDan Egnor        printf(") ------\n");
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int newline = 0;
12552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    for (;;) {
12652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        int ret = read(fd, buffer, sizeof(buffer));
12752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (ret > 0) {
12852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            newline = (buffer[ret - 1] == '\n');
12952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            ret = fwrite(buffer, ret, 1, stdout);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (ret <= 0) break;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    close(fd);
13552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (!newline) printf("\n");
13652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (title) printf("\n");
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* forks a command and waits for it to finish */
14152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorint run_command(const char *title, int timeout_seconds, const char *command, ...) {
14252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    fflush(stdout);
14352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    clock_t start = clock();
14452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    pid_t pid = fork();
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* handle error case */
14752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (pid < 0) {
14852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        printf("*** fork: %s\n", strerror(errno));
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return pid;
15052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* handle child case */
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pid == 0) {
15452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        const char *args[1024] = {command};
15552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        size_t arg;
15652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
15752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        va_list ap;
15852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        va_start(ap, command);
159ea11654e684cb91252487f697c72e76da507f7beDan Egnor        if (title) printf("------ %s (%s", title, command);
16052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
16152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            args[arg] = va_arg(ap, const char *);
16252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            if (args[arg] == NULL) break;
16352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            if (title) printf(" %s", args[arg]);
16452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
165ea11654e684cb91252487f697c72e76da507f7beDan Egnor        if (title) printf(") ------\n");
16652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fflush(stdout);
16752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
16852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        execvp(command, (char**) args);
16952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        printf("*** exec(%s): %s\n", command, strerror(errno));
17052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        _exit(-1);
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* handle parent case */
17452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    for (;;) {
17552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        int status;
17652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        pid_t p = waitpid(pid, &status, WNOHANG);
17752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        float elapsed = (float) (clock() - start) / CLOCKS_PER_SEC;
17852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (p == pid) {
17952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            if (WIFSIGNALED(status)) {
18052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor                printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
18152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            } else if (WEXITSTATUS(status) > 0) {
18252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor                printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
18352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            }
18452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            if (title) printf("[%s: %.1fs elapsed]\n\n", command, elapsed);
18552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            return status;
18652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (timeout_seconds && elapsed > timeout_seconds) {
18952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            printf("*** %s: Timed out after %.1fs (killing pid %d)\n", command, elapsed, pid);
19052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            kill(pid, SIGTERM);
19152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            return -1;
19252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        usleep(100000);  // poll every 0.1 sec
19552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
19652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor}
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorsize_t num_props = 0;
19952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorstatic char* props[2000];
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorstatic void print_prop(const char *key, const char *name, void *user) {
20252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    (void) user;
20352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (num_props < sizeof(props) / sizeof(props[0])) {
20452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        char buf[PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 10];
20552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        snprintf(buf, sizeof(buf), "[%s]: [%s]\n", key, name);
20652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        props[num_props++] = strdup(buf);
20752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorstatic int compare_prop(const void *a, const void *b) {
21152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    return strcmp(*(char * const *) a, *(char * const *) b);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* prints all the system properties */
21552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorvoid print_properties() {
21652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    size_t i;
21752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    num_props = 0;
21852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    property_list(print_prop, NULL);
21952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    qsort(&props, num_props, sizeof(props[0]), compare_prop);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
221ea11654e684cb91252487f697c72e76da507f7beDan Egnor    printf("------ SYSTEM PROPERTIES ------\n");
22252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    for (i = 0; i < num_props; ++i) {
22352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fputs(props[i], stdout);
22452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        free(props[i]);
22552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
22652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    printf("\n");
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* redirect output to a service control socket */
23052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorvoid redirect_to_socket(FILE *redirect, const char *service) {
23152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int s = android_get_control_socket(service);
23252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (s < 0) {
23352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno));
23452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        exit(1);
23552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
23652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (listen(s, 4) < 0) {
23752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "listen(control socket): %s\n", strerror(errno));
23852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        exit(1);
23952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    struct sockaddr addr;
24252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    socklen_t alen = sizeof(addr);
24352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int fd = accept(s, &addr, &alen);
24452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (fd < 0) {
24552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "accept(control socket): %s\n", strerror(errno));
24652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        exit(1);
24752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    fflush(redirect);
25052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    dup2(fd, fileno(redirect));
25152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    close(fd);
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* redirect output to a file, optionally gzipping; returns gzip pid (or -1) */
25552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorpid_t redirect_to_file(FILE *redirect, char *path, int gzip_level) {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *chp = path;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* skip initial slash */
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (chp[0] == '/')
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        chp++;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    /* create leading directories, if necessary */
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (chp && chp[0]) {
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        chp = strchr(chp, '/');
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (chp) {
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *chp = 0;
26752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            mkdir(path, 0775);  /* drwxrwxr-x */
26852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            *chp++ = '/';
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
27352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (fd < 0) {
27452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "%s: %s\n", path, strerror(errno));
27552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        exit(1);
27652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
27752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
27852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    pid_t gzip_pid = -1;
27952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (gzip_level > 0) {
28052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        int fds[2];
28152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (pipe(fds)) {
28252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            fprintf(stderr, "pipe: %s\n", strerror(errno));
28352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            exit(1);
28452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
28552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
28652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fflush(redirect);
28752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fflush(stdout);
28852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
28952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        gzip_pid = fork();
29052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (gzip_pid < 0) {
29152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            fprintf(stderr, "fork: %s\n", strerror(errno));
29252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            exit(1);
29352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
29452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
29552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (gzip_pid == 0) {
29652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            dup2(fds[0], STDIN_FILENO);
29752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            dup2(fd, STDOUT_FILENO);
29852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
29952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            close(fd);
30052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            close(fds[0]);
30152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            close(fds[1]);
30252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
30352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            char level[10];
30452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            snprintf(level, sizeof(level), "-%d", gzip_level);
30552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            execlp("gzip", "gzip", level, NULL);
30652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            fprintf(stderr, "exec(gzip): %s\n", strerror(errno));
30752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            _exit(-1);
30852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
30952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
31052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        close(fd);
31152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        close(fds[0]);
31252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fd = fds[1];
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
31452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
31552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    dup2(fd, fileno(redirect));
31652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    close(fd);
31752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    return gzip_pid;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* dump Dalvik stack traces, return the trace file location (NULL if none) */
32152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorconst char *dump_vm_traces() {
32252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    char traces_path[PROPERTY_VALUE_MAX] = "";
32352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    property_get("dalvik.vm.stack-trace-file", traces_path, "");
32452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (!traces_path[0]) return NULL;
32552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
32652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    /* move the old traces.txt (if any) out of the way temporarily */
32752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    char anr_traces_path[PATH_MAX];
32852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
32952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
3306a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor    if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
3316a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
3326a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor        return NULL;  // Can't rename old traces.txt -- no permission? -- leave it alone instead
3336a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor    }
33452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
335efd13938013099e58f4dcbf818f508c585547817Dan Egnor    /* make the directory if necessary */
336efd13938013099e58f4dcbf818f508c585547817Dan Egnor    char anr_traces_dir[PATH_MAX];
337efd13938013099e58f4dcbf818f508c585547817Dan Egnor    strlcpy(anr_traces_dir, traces_path, sizeof(anr_traces_dir));
338efd13938013099e58f4dcbf818f508c585547817Dan Egnor    char *slash = strrchr(anr_traces_dir, '/');
339efd13938013099e58f4dcbf818f508c585547817Dan Egnor    if (slash != NULL) {
340efd13938013099e58f4dcbf818f508c585547817Dan Egnor        *slash = '\0';
341efd13938013099e58f4dcbf818f508c585547817Dan Egnor        if (!mkdir(anr_traces_dir, 0775)) {
342efd13938013099e58f4dcbf818f508c585547817Dan Egnor            chown(anr_traces_dir, AID_SYSTEM, AID_SYSTEM);
343efd13938013099e58f4dcbf818f508c585547817Dan Egnor        } else if (errno != EEXIST) {
344efd13938013099e58f4dcbf818f508c585547817Dan Egnor            fprintf(stderr, "mkdir(%s): %s\n", anr_traces_dir, strerror(errno));
345efd13938013099e58f4dcbf818f508c585547817Dan Egnor            return NULL;
346efd13938013099e58f4dcbf818f508c585547817Dan Egnor        }
347efd13938013099e58f4dcbf818f508c585547817Dan Egnor    }
348efd13938013099e58f4dcbf818f508c585547817Dan Egnor
34952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    /* create a new, empty traces.txt file to receive stack dumps */
35052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC, 0666);  /* -rw-rw-rw- */
35152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (fd < 0) {
35252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "%s: %s\n", traces_path, strerror(errno));
35352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        return NULL;
35452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
35552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    close(fd);
35652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
35752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    /* walk /proc and kill -QUIT all Dalvik processes */
35852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    DIR *proc = opendir("/proc");
35952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (proc == NULL) {
36052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "/proc: %s\n", strerror(errno));
36152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        return NULL;
36252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
36352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
36452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    /* use inotify to find when processes are done dumping */
36552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int ifd = inotify_init();
36652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (ifd < 0) {
36752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "inotify_init: %s\n", strerror(errno));
36852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        return NULL;
36952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
37052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
37152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    int wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE);
37252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (wfd < 0) {
37352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
37452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        return NULL;
37552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    struct dirent *d;
378efd13938013099e58f4dcbf818f508c585547817Dan Egnor    int dalvik_found = 0;
37952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    while ((d = readdir(proc))) {
38052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        int pid = atoi(d->d_name);
38152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (pid <= 0) continue;
38252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
38352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        /* identify Dalvik: /proc/(pid)/exe = /system/bin/app_process */
38452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        char path[PATH_MAX], data[PATH_MAX];
38552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        snprintf(path, sizeof(path), "/proc/%d/exe", pid);
38652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        size_t len = readlink(path, data, sizeof(data) - 1);
38752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (len <= 0 || memcmp(data, "/system/bin/app_process", 23)) continue;
38852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
38952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        /* skip zygote -- it won't dump its stack anyway */
39052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
39152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        int fd = open(path, O_RDONLY);
39252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        len = read(fd, data, sizeof(data) - 1);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(fd);
39452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (len <= 0 || !memcmp(data, "zygote", 6)) continue;
39552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
396efd13938013099e58f4dcbf818f508c585547817Dan Egnor        ++dalvik_found;
39752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (kill(pid, SIGQUIT)) {
39852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
39952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            continue;
40052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
40152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
40252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        /* wait for the writable-close notification from inotify */
40352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        struct pollfd pfd = { ifd, POLLIN, 0 };
40452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        int ret = poll(&pfd, 1, 200);  /* 200 msec timeout */
40552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        if (ret < 0) {
40652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            fprintf(stderr, "poll: %s\n", strerror(errno));
40752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        } else if (ret == 0) {
40852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            fprintf(stderr, "warning: timed out dumping pid %d\n", pid);
40952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        } else {
41052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            struct inotify_event ie;
41152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor            read(ifd, &ie, sizeof(ie));
41252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
41452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
41552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    close(ifd);
416efd13938013099e58f4dcbf818f508c585547817Dan Egnor    if (dalvik_found == 0) {
417efd13938013099e58f4dcbf818f508c585547817Dan Egnor        fprintf(stderr, "Warning: no Dalvik processes found to dump stacks\n");
418efd13938013099e58f4dcbf818f508c585547817Dan Egnor    }
41952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
42052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    static char dump_traces_path[PATH_MAX];
42152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path));
42252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path));
42352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    if (rename(traces_path, dump_traces_path)) {
42452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
42552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor        return NULL;
42652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    }
42752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor
42852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    /* replace the saved [ANR] traces.txt file */
42952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    rename(anr_traces_path, traces_path);
43052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor    return dump_traces_path;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
432