summaryrefslogtreecommitdiffstats
path: root/runtime/signal_catcher.cc
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2017-04-07 15:41:41 +0100
committerNarayan Kamath <narayan@google.com>2017-04-25 11:30:33 +0100
commit84695aef89a3c42ea81c23f0590ae2ceca09ce6f (patch)
tree2b9d8c239e4296fd7f07b06ea8d07c5b4ea6fabd /runtime/signal_catcher.cc
parentaa03f6fa38da0166790f2b22b679e6568ad56f7d (diff)
downloadart-84695aef89a3c42ea81c23f0590ae2ceca09ce6f.tar.gz
art-84695aef89a3c42ea81c23f0590ae2ceca09ce6f.tar.bz2
art-84695aef89a3c42ea81c23f0590ae2ceca09ce6f.zip
ART: Support per PID stack trace files.
Introduce an -Xstacktracedir argument that supplies a directory under which stack traces are written, with a unique file created per trace. The location of the actual directory in a production system is still not decided, and follow up changes might be introduced to supply a per process override. Bug: 32064548 Test: test-art-host, test-art-target Change-Id: If377ce6a2abe8b325f6441d8de222b1ea3f40ec9
Diffstat (limited to 'runtime/signal_catcher.cc')
-rw-r--r--runtime/signal_catcher.cc49
1 files changed, 42 insertions, 7 deletions
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 0b7ea2ff02..382643314c 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -27,6 +27,7 @@
#include <sstream>
+#include "android-base/stringprintf.h"
#include "arch/instruction_set.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
@@ -65,8 +66,10 @@ static void DumpCmdLine(std::ostream& os) {
#endif
}
-SignalCatcher::SignalCatcher(const std::string& stack_trace_file)
- : stack_trace_file_(stack_trace_file),
+SignalCatcher::SignalCatcher(const std::string& stack_trace_dir,
+ const std::string& stack_trace_file)
+ : stack_trace_dir_(stack_trace_dir),
+ stack_trace_file_(stack_trace_file),
lock_("SignalCatcher lock"),
cond_("SignalCatcher::cond_", lock_),
thread_(nullptr) {
@@ -100,19 +103,51 @@ bool SignalCatcher::ShouldHalt() {
return halt_;
}
+std::string SignalCatcher::GetStackTraceFileName() {
+ if (!stack_trace_dir_.empty()) {
+ // We'll try a maximum of ten times (arbitrarily selected) to create a file
+ // with a unique name, seeding the pseudo random generator each time.
+ //
+ // If this doesn't work, give up and log to stdout. Note that we could try
+ // indefinitely, but that would make problems in this code harder to detect
+ // since we'd be spinning in the signal catcher thread.
+ static constexpr uint32_t kMaxRetries = 10;
+
+ for (uint32_t i = 0; i < kMaxRetries; ++i) {
+ std::srand(NanoTime());
+ // Sample output for PID 1234 : /data/anr-pid1234-cafeffee.txt
+ const std::string file_name = android::base::StringPrintf(
+ "%s/anr-pid%" PRId32 "-%08" PRIx32 ".txt",
+ stack_trace_dir_.c_str(),
+ static_cast<int32_t>(getpid()),
+ static_cast<uint32_t>(std::rand()));
+
+ if (!OS::FileExists(file_name.c_str())) {
+ return file_name;
+ }
+ }
+
+ LOG(ERROR) << "Unable to obtain stack trace filename at path : " << stack_trace_dir_;
+ return "";
+ }
+
+ return stack_trace_file_;
+}
+
void SignalCatcher::Output(const std::string& s) {
- if (stack_trace_file_.empty()) {
+ const std::string stack_trace_file = GetStackTraceFileName();
+ if (stack_trace_file.empty()) {
LOG(INFO) << s;
return;
}
ScopedThreadStateChange tsc(Thread::Current(), kWaitingForSignalCatcherOutput);
- int fd = open(stack_trace_file_.c_str(), O_APPEND | O_CREAT | O_WRONLY, 0666);
+ int fd = open(stack_trace_file.c_str(), O_APPEND | O_CREAT | O_WRONLY, 0666);
if (fd == -1) {
PLOG(ERROR) << "Unable to open stack trace file '" << stack_trace_file_ << "'";
return;
}
- std::unique_ptr<File> file(new File(fd, stack_trace_file_, true));
+ std::unique_ptr<File> file(new File(fd, stack_trace_file, true));
bool success = file->WriteFully(s.data(), s.size());
if (success) {
success = file->FlushCloseOrErase() == 0;
@@ -120,9 +155,9 @@ void SignalCatcher::Output(const std::string& s) {
file->Erase();
}
if (success) {
- LOG(INFO) << "Wrote stack traces to '" << stack_trace_file_ << "'";
+ LOG(INFO) << "Wrote stack traces to '" << stack_trace_file << "'";
} else {
- PLOG(ERROR) << "Failed to write stack traces to '" << stack_trace_file_ << "'";
+ PLOG(ERROR) << "Failed to write stack traces to '" << stack_trace_file << "'";
}
}