Loading cmds/dumpstate/bugreport-format.md +2 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ The zip file also contains 2 metadata entries generated by `dumpstate`: under the `FS` folder. For example, a `/dirA/dirB/fileC` file in the device would generate a `FS/dirA/dirB/fileC` entry in the zip file. When systrace is enabled, the zip file will contain a `systrace.txt` file as well. The flat file also has some minor changes: - Tombstone files were removed and added to the zip file. Loading cmds/dumpstate/dumpstate.cpp +42 −1 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ static std::unique_ptr<ZipWriter> zip_writer; static std::set<std::string> mount_points; void add_mountinfo(); static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path); static bool add_zip_entry_from_fd(const std::string& entry_name, int fd); #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops" Loading Loading @@ -90,7 +91,7 @@ const std::string& ZIP_ROOT_DIR = "FS"; * See bugreport-format.txt for more info. */ // TODO: change to "v1" before final N build static std::string VERSION_DEFAULT = "v1-dev2"; static std::string VERSION_DEFAULT = "v1-dev3"; /* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones, * otherwise gets just those modified in the last half an hour. */ Loading Loading @@ -168,6 +169,42 @@ static void dump_dev_files(const char *title, const char *driverpath, const char closedir(d); } static void dump_systrace() { if (!zip_writer) { MYLOGD("Not dumping systrace because zip_writer is not set\n"); return; } const char* path = "/sys/kernel/debug/tracing/tracing_on"; long int is_tracing; if (read_file_as_long(path, &is_tracing)) { return; // error already logged } if (is_tracing <= 0) { MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing); return; } DurationReporter duration_reporter("SYSTRACE", nullptr); // systrace output can be many MBs, so we need to redirect its stdout straigh to the zip file by // forking and using a pipe. int pipefd[2]; pipe(pipefd); if (fork() == 0) { close(pipefd[0]); // close reading end in the child dup2(pipefd[1], STDOUT_FILENO); // send stdout to the pipe dup2(pipefd[1], STDERR_FILENO); // send stderr to the pipe close(pipefd[1]); // this descriptor is no longer needed // TODO: ideally it should use run_command, but it doesn't work well with pipes. // The drawback of calling execl directly is that we're not timing out if it hangs. MYLOGD("Running '/system/bin/atrace --async_dump', which can take several seconds"); execl("/system/bin/atrace", "/system/bin/atrace", "--async_dump", nullptr); } else { close(pipefd[1]); // close the write end of the pipe in the parent add_zip_entry_from_fd("systrace.txt", pipefd[0]); // write output to zip file } } static bool skip_not_stat(const char *path) { static const char stat[] = "/stat"; size_t len = strlen(path); Loading Loading @@ -1252,11 +1289,15 @@ int main(int argc, char *argv[]) { // duration is logged into MYLOG instead. print_header(version); // Dumps systrace right away, otherwise it will be filled with unnecessary events. dump_systrace(); // Invoking the following dumpsys calls before dump_traces() to try and // keep the system stats as close to its initial state as possible. run_command("DUMPSYS MEMINFO", 30, SU_PATH, "shell", "dumpsys", "meminfo", "-a", NULL); run_command("DUMPSYS CPUINFO", 30, SU_PATH, "shell", "dumpsys", "cpuinfo", "-a", NULL); /* collect stack traces from Dalvik and native processes (needs root) */ dump_traces_path = dump_traces(); Loading cmds/dumpstate/dumpstate.h +3 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,9 @@ extern int do_update_progress, progress, weight_total; /* prints the contents of a file */ int dump_file(const char *title, const char *path); /* saves the the contents of a file as a long */ int read_file_as_long(const char *path, long int *output); /* prints the contents of the fd * fd must have been opened with the flag O_NONBLOCK. */ Loading cmds/dumpstate/utils.cpp +21 −1 Original line number Diff line number Diff line Loading @@ -474,6 +474,27 @@ int dump_file(const char *title, const char *path) { return _dump_file_from_fd(title, path, fd); } int read_file_as_long(const char *path, long int *output) { int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)); if (fd < 0) { int err = errno; MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err)); return -1; } char buffer[50]; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer))); if (bytes_read == -1) { MYLOGE("Error reading file %s: %s\n", path, strerror(errno)); return -2; } if (bytes_read == 0) { MYLOGE("File %s is empty\n", path); return -3; } *output = atoi(buffer); return 0; } /* calls skip to gate calling dump_from_fd recursively * in the specified directory. dump_from_fd defaults to * dump_file_from_fd above when set to NULL. skip defaults Loading Loading @@ -677,7 +698,6 @@ int run_command_always(const char *title, int timeout_seconds, const char *args[ execvp(command, (char**) args); // execvp's result will be handled after waitpid_with_timeout() below... _exit(-1); // ...but it doesn't hurt to force exit, just in case } /* handle parent case */ Loading Loading
cmds/dumpstate/bugreport-format.md +2 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ The zip file also contains 2 metadata entries generated by `dumpstate`: under the `FS` folder. For example, a `/dirA/dirB/fileC` file in the device would generate a `FS/dirA/dirB/fileC` entry in the zip file. When systrace is enabled, the zip file will contain a `systrace.txt` file as well. The flat file also has some minor changes: - Tombstone files were removed and added to the zip file. Loading
cmds/dumpstate/dumpstate.cpp +42 −1 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ static std::unique_ptr<ZipWriter> zip_writer; static std::set<std::string> mount_points; void add_mountinfo(); static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path); static bool add_zip_entry_from_fd(const std::string& entry_name, int fd); #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops" Loading Loading @@ -90,7 +91,7 @@ const std::string& ZIP_ROOT_DIR = "FS"; * See bugreport-format.txt for more info. */ // TODO: change to "v1" before final N build static std::string VERSION_DEFAULT = "v1-dev2"; static std::string VERSION_DEFAULT = "v1-dev3"; /* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones, * otherwise gets just those modified in the last half an hour. */ Loading Loading @@ -168,6 +169,42 @@ static void dump_dev_files(const char *title, const char *driverpath, const char closedir(d); } static void dump_systrace() { if (!zip_writer) { MYLOGD("Not dumping systrace because zip_writer is not set\n"); return; } const char* path = "/sys/kernel/debug/tracing/tracing_on"; long int is_tracing; if (read_file_as_long(path, &is_tracing)) { return; // error already logged } if (is_tracing <= 0) { MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing); return; } DurationReporter duration_reporter("SYSTRACE", nullptr); // systrace output can be many MBs, so we need to redirect its stdout straigh to the zip file by // forking and using a pipe. int pipefd[2]; pipe(pipefd); if (fork() == 0) { close(pipefd[0]); // close reading end in the child dup2(pipefd[1], STDOUT_FILENO); // send stdout to the pipe dup2(pipefd[1], STDERR_FILENO); // send stderr to the pipe close(pipefd[1]); // this descriptor is no longer needed // TODO: ideally it should use run_command, but it doesn't work well with pipes. // The drawback of calling execl directly is that we're not timing out if it hangs. MYLOGD("Running '/system/bin/atrace --async_dump', which can take several seconds"); execl("/system/bin/atrace", "/system/bin/atrace", "--async_dump", nullptr); } else { close(pipefd[1]); // close the write end of the pipe in the parent add_zip_entry_from_fd("systrace.txt", pipefd[0]); // write output to zip file } } static bool skip_not_stat(const char *path) { static const char stat[] = "/stat"; size_t len = strlen(path); Loading Loading @@ -1252,11 +1289,15 @@ int main(int argc, char *argv[]) { // duration is logged into MYLOG instead. print_header(version); // Dumps systrace right away, otherwise it will be filled with unnecessary events. dump_systrace(); // Invoking the following dumpsys calls before dump_traces() to try and // keep the system stats as close to its initial state as possible. run_command("DUMPSYS MEMINFO", 30, SU_PATH, "shell", "dumpsys", "meminfo", "-a", NULL); run_command("DUMPSYS CPUINFO", 30, SU_PATH, "shell", "dumpsys", "cpuinfo", "-a", NULL); /* collect stack traces from Dalvik and native processes (needs root) */ dump_traces_path = dump_traces(); Loading
cmds/dumpstate/dumpstate.h +3 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,9 @@ extern int do_update_progress, progress, weight_total; /* prints the contents of a file */ int dump_file(const char *title, const char *path); /* saves the the contents of a file as a long */ int read_file_as_long(const char *path, long int *output); /* prints the contents of the fd * fd must have been opened with the flag O_NONBLOCK. */ Loading
cmds/dumpstate/utils.cpp +21 −1 Original line number Diff line number Diff line Loading @@ -474,6 +474,27 @@ int dump_file(const char *title, const char *path) { return _dump_file_from_fd(title, path, fd); } int read_file_as_long(const char *path, long int *output) { int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)); if (fd < 0) { int err = errno; MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err)); return -1; } char buffer[50]; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer))); if (bytes_read == -1) { MYLOGE("Error reading file %s: %s\n", path, strerror(errno)); return -2; } if (bytes_read == 0) { MYLOGE("File %s is empty\n", path); return -3; } *output = atoi(buffer); return 0; } /* calls skip to gate calling dump_from_fd recursively * in the specified directory. dump_from_fd defaults to * dump_file_from_fd above when set to NULL. skip defaults Loading Loading @@ -677,7 +698,6 @@ int run_command_always(const char *title, int timeout_seconds, const char *args[ execvp(command, (char**) args); // execvp's result will be handled after waitpid_with_timeout() below... _exit(-1); // ...but it doesn't hurt to force exit, just in case } /* handle parent case */ Loading