Implement -Xstacktracefile.
Change-Id: Ib6c73ddc6f0eaf8f8b731d450b87bda55589f857
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index a3e7bb1..851aab7 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -16,14 +16,19 @@
#include "signal_catcher.h"
+#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
+#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/types.h>
#include <unistd.h>
#include "class_linker.h"
+#include "file.h"
#include "heap.h"
+#include "os.h"
#include "runtime.h"
#include "thread.h"
#include "thread_list.h"
@@ -31,8 +36,11 @@
namespace art {
-SignalCatcher::SignalCatcher()
- : lock_("SignalCatcher lock"), cond_("SignalCatcher::cond_"), thread_(NULL) {
+SignalCatcher::SignalCatcher(const std::string& stack_trace_file)
+ : stack_trace_file_(stack_trace_file),
+ lock_("SignalCatcher lock"),
+ cond_("SignalCatcher::cond_"),
+ thread_(NULL) {
SetHaltFlag(false);
// Create a raw pthread; its start routine will attach to the runtime.
@@ -62,6 +70,27 @@
return halt_;
}
+void SignalCatcher::Output(const std::string& s) {
+ if (stack_trace_file_.empty()) {
+ LOG(INFO) << s;
+ return;
+ }
+
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
+ 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;
+ }
+ UniquePtr<File> file(OS::FileFromFd(stack_trace_file_.c_str(), fd));
+ if (!file->WriteFully(s.data(), s.size())) {
+ PLOG(ERROR) << "Failed to write stack traces to '" << stack_trace_file_ << "'";
+ } else {
+ LOG(INFO) << "Wrote stack traces to '" << stack_trace_file_ << "'";
+ }
+ close(fd);
+}
+
void SignalCatcher::HandleSigQuit() {
Runtime* runtime = Runtime::Current();
ThreadList* thread_list = runtime->GetThreadList();
@@ -92,11 +121,11 @@
os << "/proc/self/maps:\n" << maps;
}
- os << "----- end " << getpid() << " -----";
+ os << "----- end " << getpid() << " -----\n";
thread_list->ResumeAll();
- LOG(INFO) << os.str();
+ Output(os.str());
}
void SignalCatcher::HandleSigUsr1() {
@@ -151,10 +180,10 @@
LOG(INFO) << *signal_catcher->thread_ << ": reacting to signal " << signal_number;
switch (signal_number) {
case SIGQUIT:
- HandleSigQuit();
+ signal_catcher->HandleSigQuit();
break;
case SIGUSR1:
- HandleSigUsr1();
+ signal_catcher->HandleSigUsr1();
break;
default:
LOG(ERROR) << "Unexpected signal %d" << signal_number;