Merge "Dumpstate's netstat call should use -W."
diff --git a/cmds/dumpstate/bugreport-format.md b/cmds/dumpstate/bugreport-format.md
index 388b506..b995b80 100644
--- a/cmds/dumpstate/bugreport-format.md
+++ b/cmds/dumpstate/bugreport-format.md
@@ -55,6 +55,10 @@
- `title.txt`: whose value is a single-line summary of the problem.
- `description.txt`: whose value is a multi-line, detailed description of the problem.
+## Android O versions
+On _Android O (OhMightyAndroidWhatsYourNextReleaseName?)_, the following changes were made:
+- The ANR traces are added to the `FS` folder, typically under `FS/data/anr` (version `2.0-dev-1`).
+
## Intermediate versions
During development, the versions will be suffixed with _-devX_ or
_-devX-EXPERIMENTAL_FEATURE_, where _X_ is a number that increases as the
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index df13e4e..537ba21 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -827,6 +827,87 @@
RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
}
+static void AddAnrTraceFiles() {
+ bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+ std::string dump_traces_dir;
+
+ /* show the traces we collected in main(), if that was done */
+ if (dump_traces_path != nullptr) {
+ if (add_to_zip) {
+ dump_traces_dir = dirname(dump_traces_path);
+ MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
+ ds.AddDir(dump_traces_dir, true);
+ } else {
+ MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
+ dump_traces_path);
+ ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
+ }
+ }
+
+ std::string anr_traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+ std::string anr_traces_dir = dirname(anr_traces_path.c_str());
+
+ // Make sure directory is not added twice.
+ // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
+ // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
+ // property - but in reality they're the same path (although the former could be nullptr).
+ // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
+ // be revisited.
+ bool already_dumped = anr_traces_dir == dump_traces_dir;
+
+ MYLOGD("AddAnrTraceFiles(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
+ dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
+
+ if (anr_traces_path.empty()) {
+ printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
+ } else {
+ int fd = TEMP_FAILURE_RETRY(
+ open(anr_traces_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
+ if (fd < 0) {
+ printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path.c_str(),
+ strerror(errno));
+ } else {
+ if (add_to_zip) {
+ if (!already_dumped) {
+ MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
+ anr_traces_dir.c_str());
+ ds.AddDir(anr_traces_dir, true);
+ already_dumped = true;
+ }
+ } else {
+ MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
+ anr_traces_path.c_str());
+ dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path.c_str(), fd);
+ }
+ }
+ }
+
+ if (add_to_zip && already_dumped) {
+ MYLOGD("Already dumped directory %s to the zip file\n", anr_traces_dir.c_str());
+ return;
+ }
+
+ /* slow traces for slow operations */
+ struct stat st;
+ if (!anr_traces_path.empty()) {
+ int tail = anr_traces_path.size() - 1;
+ while (tail > 0 && anr_traces_path.at(tail) != '/') {
+ tail--;
+ }
+ int i = 0;
+ while (1) {
+ anr_traces_path = anr_traces_path.substr(0, tail + 1) +
+ android::base::StringPrintf("slow%02d.txt", i);
+ if (stat(anr_traces_path.c_str(), &st)) {
+ // No traces file at this index, done with the files.
+ break;
+ }
+ ds.DumpFile("VM TRACES WHEN SLOW", anr_traces_path.c_str());
+ i++;
+ }
+ }
+}
+
static void dumpstate() {
DurationReporter duration_reporter("DUMPSTATE");
unsigned long timeout;
@@ -904,44 +985,7 @@
RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
- /* show the traces we collected in main(), if that was done */
- if (dump_traces_path != NULL) {
- DumpFile("VM TRACES JUST NOW", dump_traces_path);
- }
-
- /* only show ANR traces if they're less than 15 minutes old */
- struct stat st;
- std::string anrTracesPath = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
- if (anrTracesPath.empty()) {
- printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
- } else {
- int fd = TEMP_FAILURE_RETRY(
- open(anrTracesPath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
- if (fd < 0) {
- printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anrTracesPath.c_str(), strerror(errno));
- } else {
- dump_file_from_fd("VM TRACES AT LAST ANR", anrTracesPath.c_str(), fd);
- }
- }
-
- /* slow traces for slow operations */
- if (!anrTracesPath.empty()) {
- int tail = anrTracesPath.size() - 1;
- while (tail > 0 && anrTracesPath.at(tail) != '/') {
- tail--;
- }
- int i = 0;
- while (1) {
- anrTracesPath =
- anrTracesPath.substr(0, tail + 1) + android::base::StringPrintf("slow%02d.txt", i);
- if (stat(anrTracesPath.c_str(), &st)) {
- // No traces file at this index, done with the files.
- break;
- }
- DumpFile("VM TRACES WHEN SLOW", anrTracesPath.c_str());
- i++;
- }
- }
+ AddAnrTraceFiles();
int dumped = 0;
for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
@@ -970,6 +1014,7 @@
DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
+ struct stat st;
if (!stat(PSTORE_LAST_KMSG, &st)) {
/* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
@@ -1368,9 +1413,10 @@
ds.version_ = VERSION_CURRENT;
}
- if (ds.version_ != VERSION_CURRENT) {
- MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s')\n",
- ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
+ if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
+ MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
+ ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
+ VERSION_SPLIT_ANR.c_str());
exit(1);
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 568256a..ab36c41c 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -200,6 +200,12 @@
static std::string VERSION_CURRENT = "1.0";
/*
+ * Temporary version that adds a anr-traces.txt entry. Once tools support it, the current version
+ * will be bumped to 2.0-dev-1.
+ */
+static std::string VERSION_SPLIT_ANR = "2.0-dev-1";
+
+/*
* "Alias" for the current version.
*/
static std::string VERSION_DEFAULT = "default";
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 31c8697..c41cca4 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -17,24 +17,25 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <libgen.h>
#include <limits.h>
#include <poll.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string>
#include <string.h>
#include <sys/capability.h>
#include <sys/inotify.h>
+#include <sys/klog.h>
+#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
-#include <sys/klog.h>
#include <time.h>
#include <unistd.h>
+#include <string>
#include <vector>
-#include <sys/prctl.h>
#define LOG_TAG "dumpstate"
@@ -1137,32 +1138,31 @@
/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
const char *dump_traces() {
- DurationReporter duration_reporter("DUMP TRACES", nullptr);
- if (IsDryRun()) return nullptr;
+ DurationReporter duration_reporter("DUMP TRACES");
const char* result = nullptr;
- std::string tracesPath = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
- if (tracesPath.empty()) return nullptr;
+ std::string traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+ if (traces_path.empty()) return nullptr;
/* move the old traces.txt (if any) out of the way temporarily */
- std::string anrTracesPath = tracesPath + ".anr";
- if (rename(tracesPath.c_str(), anrTracesPath.c_str()) && errno != ENOENT) {
- MYLOGE("rename(%s, %s): %s\n", tracesPath.c_str(), anrTracesPath.c_str(), strerror(errno));
+ std::string anrtraces_path = traces_path + ".anr";
+ if (rename(traces_path.c_str(), anrtraces_path.c_str()) && errno != ENOENT) {
+ MYLOGE("rename(%s, %s): %s\n", traces_path.c_str(), anrtraces_path.c_str(), strerror(errno));
return nullptr; // Can't rename old traces.txt -- no permission? -- leave it alone instead
}
/* create a new, empty traces.txt file to receive stack dumps */
- int fd = TEMP_FAILURE_RETRY(open(tracesPath.c_str(),
+ int fd = TEMP_FAILURE_RETRY(open(traces_path.c_str(),
O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
0666)); /* -rw-rw-rw- */
if (fd < 0) {
- MYLOGE("%s: %s\n", tracesPath.c_str(), strerror(errno));
+ MYLOGE("%s: %s\n", traces_path.c_str(), strerror(errno));
return nullptr;
}
int chmod_ret = fchmod(fd, 0666);
if (chmod_ret < 0) {
- MYLOGE("fchmod on %s failed: %s\n", tracesPath.c_str(), strerror(errno));
+ MYLOGE("fchmod on %s failed: %s\n", traces_path.c_str(), strerror(errno));
close(fd);
return nullptr;
}
@@ -1185,9 +1185,9 @@
goto error_close_fd;
}
- wfd = inotify_add_watch(ifd, tracesPath.c_str(), IN_CLOSE_WRITE);
+ wfd = inotify_add_watch(ifd, traces_path.c_str(), IN_CLOSE_WRITE);
if (wfd < 0) {
- MYLOGE("inotify_add_watch(%s): %s\n", tracesPath.c_str(), strerror(errno));
+ MYLOGE("inotify_add_watch(%s): %s\n", traces_path.c_str(), strerror(errno));
goto error_close_ifd;
}
@@ -1271,15 +1271,17 @@
MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
}
- static std::string dumpTracesPath = tracesPath + ".bugreport";
- if (rename(tracesPath.c_str(), dumpTracesPath.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", tracesPath.c_str(), dumpTracesPath.c_str(), strerror(errno));
+ static std::string dumptraces_path = android::base::StringPrintf(
+ "%s/bugreport-%s", dirname(traces_path.c_str()), basename(traces_path.c_str()));
+ if (rename(traces_path.c_str(), dumptraces_path.c_str())) {
+ MYLOGE("rename(%s, %s): %s\n", traces_path.c_str(), dumptraces_path.c_str(),
+ strerror(errno));
goto error_close_ifd;
}
- result = dumpTracesPath.c_str();
+ result = dumptraces_path.c_str();
/* replace the saved [ANR] traces.txt file */
- rename(anrTracesPath.c_str(), tracesPath.c_str());
+ rename(anrtraces_path.c_str(), traces_path.c_str());
error_close_ifd:
close(ifd);