diff options
author | 2019-03-11 09:23:09 +0000 | |
---|---|---|
committer | 2019-03-11 10:53:03 +0000 | |
commit | faafd5203ed5a47bdab9c4f7b9847968186a359e (patch) | |
tree | db95b41210bd9987026ec41730233f5048d0f5f3 | |
parent | 36415570df3c7f46ff3bd6f4f61abee66e4ff1dc (diff) |
dumpstate: move dump_traces to Dumpstate
Prefactoring to handle user consent denial sooner.
BUG: 128270426
Test: adb shell
/data/nativetest64/dumpstate_smoke_test/dumpstate_smoke_test &&
adb shell /data/nativetest64/dumpstate_test/dumpstate_test
Change-Id: Ifbace4391d22901480e41d3125d8a89508ebd52d
-rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 112 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.h | 6 | ||||
-rw-r--r-- | cmds/dumpstate/utils.cpp | 111 |
3 files changed, 114 insertions, 115 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 3c47767c18..5b4317224a 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -54,7 +54,9 @@ #include <android/os/IIncidentCompanion.h> #include <cutils/native_handle.h> #include <cutils/properties.h> +#include <debuggerd/client.h> #include <dumpsys.h> +#include <dumputils/dump_utils.h> #include <hidl/ServiceManagement.h> #include <openssl/sha.h> #include <private/android_filesystem_config.h> @@ -1444,7 +1446,7 @@ static bool DumpstateDefault() { RunDumpsysCritical(); /* collect stack traces from Dalvik and native processes (needs root) */ - dump_traces_path = dump_traces(); + dump_traces_path = ds.DumpTraces(); /* Run some operations that require root. */ ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()); @@ -1581,6 +1583,114 @@ static void DumpstateWifiOnly() { printf("========================================================\n"); } +const char* Dumpstate::DumpTraces() { + DurationReporter duration_reporter("DUMP TRACES"); + + const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX"; + const size_t buf_size = temp_file_pattern.length() + 1; + std::unique_ptr<char[]> file_name_buf(new char[buf_size]); + memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size); + + // Create a new, empty file to receive all trace dumps. + // + // TODO: This can be simplified once we remove support for the old style + // dumps. We can have a file descriptor passed in to dump_traces instead + // of creating a file, closing it and then reopening it again. + android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC)); + if (fd < 0) { + MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno)); + return nullptr; + } + + // Nobody should have access to this temporary file except dumpstate, but we + // temporarily grant 'read' to 'others' here because this file is created + // when tombstoned is still running as root, but dumped after dropping. This + // can go away once support for old style dumping has. + const int chmod_ret = fchmod(fd, 0666); + if (chmod_ret < 0) { + MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno)); + return nullptr; + } + + std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir); + if (proc.get() == nullptr) { + MYLOGE("opendir /proc failed: %s\n", strerror(errno)); + return nullptr; + } + + // Number of times process dumping has timed out. If we encounter too many + // failures, we'll give up. + int timeout_failures = 0; + bool dalvik_found = false; + + const std::set<int> hal_pids = get_interesting_hal_pids(); + + struct dirent* d; + while ((d = readdir(proc.get()))) { + int pid = atoi(d->d_name); + if (pid <= 0) { + continue; + } + + const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid); + std::string exe; + if (!android::base::Readlink(link_name, &exe)) { + continue; + } + + bool is_java_process; + if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") { + // Don't bother dumping backtraces for the zygote. + if (IsZygote(pid)) { + continue; + } + + dalvik_found = true; + is_java_process = true; + } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) { + is_java_process = false; + } else { + // Probably a native process we don't care about, continue. + continue; + } + + // If 3 backtrace dumps fail in a row, consider debuggerd dead. + if (timeout_failures == 3) { + dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n"); + break; + } + + const uint64_t start = Nanotime(); + const int ret = dump_backtrace_to_file_timeout( + pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, + is_java_process ? 5 : 20, fd); + + if (ret == -1) { + // For consistency, the header and footer to this message match those + // dumped by debuggerd in the success case. + dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid); + dprintf(fd, "Dump failed, likely due to a timeout.\n"); + dprintf(fd, "---- end %d ----", pid); + timeout_failures++; + continue; + } + + // We've successfully dumped stack traces, reset the failure count + // and write a summary of the elapsed time to the file and continue with the + // next process. + timeout_failures = 0; + + dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native", + pid, (float)(Nanotime() - start) / NANOS_PER_SEC); + } + + if (!dalvik_found) { + MYLOGE("Warning: no Dalvik processes found to dump stacks\n"); + } + + return file_name_buf.release(); +} + void Dumpstate::DumpstateBoard() { DurationReporter duration_reporter("dumpstate_board()"); printf("========================================================\n"); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index c326bb6bfa..686f1c5671 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -291,6 +291,9 @@ class Dumpstate { // TODO: temporary method until Dumpstate object is properly set void SetProgress(std::unique_ptr<Progress> progress); + // Dumps Dalvik and native stack traces, return the trace file location (nullptr if none). + const char* DumpTraces(); + void DumpstateBoard(); /* @@ -543,9 +546,6 @@ bool redirect_to_existing_file(FILE* redirect, char* path); /* create leading directories, if necessary */ void create_parent_dirs(const char *path); -/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */ -const char *dump_traces(); - /* for each process in the system, run the specified function */ void for_each_pid(for_each_pid_func func, const char *header); diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp index 2a5516d7f5..802c1b1570 100644 --- a/cmds/dumpstate/utils.cpp +++ b/cmds/dumpstate/utils.cpp @@ -50,8 +50,6 @@ #include <android-base/unique_fd.h> #include <cutils/properties.h> #include <cutils/sockets.h> -#include <debuggerd/client.h> -#include <dumputils/dump_utils.h> #include <log/log.h> #include <private/android_filesystem_config.h> @@ -795,115 +793,6 @@ bool redirect_to_existing_file(FILE* redirect, char* path) { return _redirect_to_file(redirect, path, O_APPEND); } -// Dump Dalvik and native stack traces, return the trace file location (nullptr if none). -const char* dump_traces() { - DurationReporter duration_reporter("DUMP TRACES"); - - const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX"; - const size_t buf_size = temp_file_pattern.length() + 1; - std::unique_ptr<char[]> file_name_buf(new char[buf_size]); - memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size); - - // Create a new, empty file to receive all trace dumps. - // - // TODO: This can be simplified once we remove support for the old style - // dumps. We can have a file descriptor passed in to dump_traces instead - // of creating a file, closing it and then reopening it again. - android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC)); - if (fd < 0) { - MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno)); - return nullptr; - } - - // Nobody should have access to this temporary file except dumpstate, but we - // temporarily grant 'read' to 'others' here because this file is created - // when tombstoned is still running as root, but dumped after dropping. This - // can go away once support for old style dumping has. - const int chmod_ret = fchmod(fd, 0666); - if (chmod_ret < 0) { - MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno)); - return nullptr; - } - - std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir); - if (proc.get() == nullptr) { - MYLOGE("opendir /proc failed: %s\n", strerror(errno)); - return nullptr; - } - - // Number of times process dumping has timed out. If we encounter too many - // failures, we'll give up. - int timeout_failures = 0; - bool dalvik_found = false; - - const std::set<int> hal_pids = get_interesting_hal_pids(); - - struct dirent* d; - while ((d = readdir(proc.get()))) { - int pid = atoi(d->d_name); - if (pid <= 0) { - continue; - } - - const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid); - std::string exe; - if (!android::base::Readlink(link_name, &exe)) { - continue; - } - - bool is_java_process; - if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") { - // Don't bother dumping backtraces for the zygote. - if (IsZygote(pid)) { - continue; - } - - dalvik_found = true; - is_java_process = true; - } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) { - is_java_process = false; - } else { - // Probably a native process we don't care about, continue. - continue; - } - - // If 3 backtrace dumps fail in a row, consider debuggerd dead. - if (timeout_failures == 3) { - dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n"); - break; - } - - const uint64_t start = Nanotime(); - const int ret = dump_backtrace_to_file_timeout( - pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, - is_java_process ? 5 : 20, fd); - - if (ret == -1) { - // For consistency, the header and footer to this message match those - // dumped by debuggerd in the success case. - dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid); - dprintf(fd, "Dump failed, likely due to a timeout.\n"); - dprintf(fd, "---- end %d ----", pid); - timeout_failures++; - continue; - } - - // We've successfully dumped stack traces, reset the failure count - // and write a summary of the elapsed time to the file and continue with the - // next process. - timeout_failures = 0; - - dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native", - pid, (float)(Nanotime() - start) / NANOS_PER_SEC); - } - - if (!dalvik_found) { - MYLOGE("Warning: no Dalvik processes found to dump stacks\n"); - } - - return file_name_buf.release(); -} - void dump_route_tables() { DurationReporter duration_reporter("DUMP ROUTE TABLES"); if (PropertiesHelper::IsDryRun()) return; |