diff options
| author | 2012-04-24 10:43:17 -0700 | |
|---|---|---|
| committer | 2012-04-24 10:54:55 -0700 | |
| commit | ae80b493748c5b6ffe310a91c651e7043f4b2dae (patch) | |
| tree | cb84ce54ebf1a29dc20889039af4219fcd09f9dd | |
| parent | b6636b8ef90221eaf7f4779eb2c2256f560d3e64 (diff) | |
Include JNI details in the SIGQUIT output.
Also include the original command line (framework apps deliberately clobber
their argv[]).
Change-Id: I63e04cb637fa89764e8963f3d086806ae230e953
| -rw-r--r-- | src/heap.cc | 4 | ||||
| -rw-r--r-- | src/hprof/hprof.cc | 2 | ||||
| -rw-r--r-- | src/hprof/hprof.h | 2 | ||||
| -rw-r--r-- | src/jni_internal.cc | 45 | ||||
| -rw-r--r-- | src/jni_internal.h | 3 | ||||
| -rw-r--r-- | src/runtime.cc | 5 | ||||
| -rw-r--r-- | src/signal_catcher.cc | 26 | ||||
| -rw-r--r-- | src/signal_catcher.h | 1 | ||||
| -rw-r--r-- | src/thread_linux.cc | 2 |
9 files changed, 76 insertions, 14 deletions
diff --git a/src/heap.cc b/src/heap.cc index b4bc7cee85..02e3ac74ea 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -51,7 +51,7 @@ static void UpdateFirstAndLastSpace(Space** first_space, Space** last_space, Spa } } -static bool GenerateImage(const std::string image_file_name) { +static bool GenerateImage(const std::string& image_file_name) { const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString()); std::vector<std::string> boot_class_path; Split(boot_class_path_string, ':', boot_class_path); @@ -660,7 +660,7 @@ void Heap::WaitForConcurrentGcToComplete() { void Heap::DumpForSigQuit(std::ostream& os) { os << "Heap: " << GetPercentFree() << "% free, " << PrettySize(num_bytes_allocated_) << "/" << PrettySize(GetTotalMemory()) - << "; " << num_objects_allocated_ << " objects"; + << "; " << num_objects_allocated_ << " objects\n"; } size_t Heap::GetPercentFree() { diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc index ccebca5da5..eacc73f9bb 100644 --- a/src/hprof/hprof.cc +++ b/src/hprof/hprof.cc @@ -647,7 +647,7 @@ HprofStringId Hprof::LookupStringId(const char* string) { return LookupStringId(std::string(string)); } -HprofStringId Hprof::LookupStringId(std::string string) { +HprofStringId Hprof::LookupStringId(const std::string& string) { StringMapIterator it = strings_.find(string); if (it != strings_.end()) { return it->second; diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h index bcdbef8111..e2f7ce1f05 100644 --- a/src/hprof/hprof.h +++ b/src/hprof/hprof.h @@ -196,7 +196,7 @@ class Hprof { HprofClassObjectId LookupClassId(Class* c); HprofStringId LookupStringId(String* string); HprofStringId LookupStringId(const char* string); - HprofStringId LookupStringId(std::string string); + HprofStringId LookupStringId(const std::string& string); HprofStringId LookupClassNameId(Class* c); static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeOut); static HprofBasicType PrimitiveToBasicTypeAndSize(Primitive::Type prim, size_t* sizeOut); diff --git a/src/jni_internal.cc b/src/jni_internal.cc index 1e2760453f..846a717dca 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -659,6 +659,21 @@ class Libraries { STLDeleteValues(&libraries_); } + void Dump(std::ostream& os) const { + bool first = true; + for (It it = libraries_.begin(); it != libraries_.end(); ++it) { + if (!first) { + os << ' '; + } + first = false; + os << it->first; + } + } + + size_t size() const { + return libraries_.size(); + } + SharedLibrary* Get(const std::string& path) { It it = libraries_.find(path); return (it == libraries_.end()) ? NULL : it->second; @@ -698,7 +713,7 @@ class Libraries { } private: - typedef SafeMap<std::string, SharedLibrary*>::iterator It; // TODO: C++0x auto + typedef SafeMap<std::string, SharedLibrary*>::const_iterator It; // TODO: C++0x auto SafeMap<std::string, SharedLibrary*> libraries_; }; @@ -2783,6 +2798,34 @@ void JavaVMExt::SetCheckJniEnabled(bool enabled) { functions = enabled ? GetCheckJniInvokeInterface() : &gJniInvokeInterface; } +void JavaVMExt::DumpForSigQuit(std::ostream& os) { + os << "JNI: CheckJNI is " << (check_jni ? "on" : "off"); + if (force_copy) { + os << " (with forcecopy)"; + } + os << "; workarounds are " << (work_around_app_jni_bugs ? "on" : "off"); + { + MutexLock mu(pins_lock); + os << "; pins=" << pin_table.Size(); + } + { + MutexLock mu(globals_lock); + os << "; globals=" << globals.Capacity(); + } + { + MutexLock mu(weak_globals_lock); + if (weak_globals.Capacity() > 0) { + os << " (plus " << weak_globals.Capacity() << " weak)"; + } + } + os << '\n'; + + { + MutexLock mu(libraries_lock); + os << "Libraries: " << Dumpable<Libraries>(*libraries) << " (" << libraries->size() << ")\n"; + } +} + void JavaVMExt::DumpReferenceTables() { { MutexLock mu(globals_lock); diff --git a/src/jni_internal.h b/src/jni_internal.h index 312b7548a2..e12a7cd6de 100644 --- a/src/jni_internal.h +++ b/src/jni_internal.h @@ -26,6 +26,7 @@ #include "reference_table.h" #include "runtime.h" +#include <iosfwd> #include <string> namespace art { @@ -97,6 +98,8 @@ struct JavaVMExt : public JavaVM { */ void* FindCodeForNativeMethod(Method* m); + void DumpForSigQuit(std::ostream& os); + void DumpReferenceTables(); void SetCheckJniEnabled(bool enabled); diff --git a/src/runtime.cc b/src/runtime.cc index 8fe760ec63..18d40f5ee8 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -491,10 +491,6 @@ Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, b parsed->heap_growth_limit_ = parsed->heap_maximum_size_; } - LOG(INFO) << "Build type: " - << (kIsDebugBuild ? "debug" : "optimized") - << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off"); - return parsed.release(); } @@ -754,6 +750,7 @@ void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { void Runtime::DumpForSigQuit(std::ostream& os) { GetClassLinker()->DumpForSigQuit(os); GetInternTable()->DumpForSigQuit(os); + GetJavaVM()->DumpForSigQuit(os); GetHeap()->DumpForSigQuit(os); os << "\n"; diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc index 5a9bf4eff9..0703b6105d 100644 --- a/src/signal_catcher.cc +++ b/src/signal_catcher.cc @@ -38,6 +38,14 @@ namespace art { +static bool ReadCmdLine(std::string& result) { + if (!ReadFileToString("/proc/self/cmdline", &result)) { + return false; + } + std::replace(result.begin(), result.end(), '\0', ' '); + return true; +} + SignalCatcher::SignalCatcher(const std::string& stack_trace_file) : stack_trace_file_(stack_trace_file), lock_("SignalCatcher lock"), @@ -45,6 +53,10 @@ SignalCatcher::SignalCatcher(const std::string& stack_trace_file) thread_(NULL) { SetHaltFlag(false); + // Stash the original command line for SIGQUIT reporting. + // By then, /proc/self/cmdline will have been rewritten to something like "system_server". + CHECK(ReadCmdLine(cmd_line_)); + // Create a raw pthread; its start routine will attach to the runtime. CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Run, this), "signal catcher thread"); @@ -109,11 +121,17 @@ void SignalCatcher::HandleSigQuit() { os << "\n" << "----- pid " << getpid() << " at " << GetIsoDate() << " -----\n"; - std::string cmdline; - if (ReadFileToString("/proc/self/cmdline", &cmdline)) { - std::replace(cmdline.begin(), cmdline.end(), '\0', ' '); - os << "Cmd line: " << cmdline << "\n"; + std::string current_cmd_line; + if (ReadCmdLine(current_cmd_line) && current_cmd_line != cmd_line_) { + os << "Cmdline: " << current_cmd_line; } + os << "\n"; + + if (current_cmd_line != cmd_line_) { + os << "Original command line: " << cmd_line_ << "\n"; + } + + os << "Build type: " << (kIsDebugBuild ? "debug" : "optimized") << "\n"; runtime->DumpForSigQuit(os); diff --git a/src/signal_catcher.h b/src/signal_catcher.h index 131b07c95b..da61ceba92 100644 --- a/src/signal_catcher.h +++ b/src/signal_catcher.h @@ -52,6 +52,7 @@ class SignalCatcher { ConditionVariable cond_; pthread_t pthread_; Thread* thread_; + std::string cmd_line_; }; } // namespace art diff --git a/src/thread_linux.cc b/src/thread_linux.cc index 314668d7a3..8eb8813722 100644 --- a/src/thread_linux.cc +++ b/src/thread_linux.cc @@ -19,7 +19,7 @@ namespace art { void Thread::DumpNativeStack(std::ostream&) const { - // TODO: use glibc backtrace(3). + // TODO: use libcorkscrew; backtrace(3) only works for the calling thread. } void Thread::SetNativePriority(int) { |