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