Include held locks in SIGQUIT thread dumps.
Handy if you have an ANR that's locking related. Quick tour:
at org.apache.harmony.dalvik.NativeTestTarget.emptyJniStaticSynchronizedMethod0(Native method)
- locked <0x60135aa8> (a java.lang.Class<org.apache.harmony.dalvik.NativeTestTarget>)
at java.lang.reflect.Method.invoke(Native method)
at C.whileTrue(Main.java:63)
at C.synchronizedOnClassString(Main.java:56)
- locked <0x60002a70> (a java.lang.Class<java.lang.String>)
at C.nestedSynchronizationWithTryCatch(Main.java:44)
- locked <0x61336b90> (a java.lang.String)
- locked <0x61336bd0> (a java.lang.String)
at C.nestedSynchronization(Main.java:35)
- locked <0x61336b18> (a java.lang.String)
- locked <0x61336b50> (a java.lang.String)
at C.synchronizedOnClassC(Main.java:30)
- locked <0x613366f8> (a java.lang.Class<C>)
at C.noLocks(Main.java:27)
at C.<clinit>(Main.java:24)
- locked <0x613366f8> (a java.lang.Class<C>)
at Main.main(Main.java:19)
A non-static synchronized native method works too:
at org.apache.harmony.dalvik.NativeTestTarget.emptyJniSynchronizedMethod0(Native method)
- locked <0x613371a8> (a org.apache.harmony.dalvik.NativeTestTarget)
...
Note that most stack traces don't look any different; the above is a
pathological example that exercises different kinds of locking. Testing
with system_server shows most threads don't hold any locks.
Future work (marked by TODO) is that explicit JNI MonitorEnter calls in
native code aren't shown.
Change-Id: I2747f5cddb4ef64b1935736f084a68fe8e4005e9
diff --git a/src/debugger.cc b/src/debugger.cc
index 147a9b6..9dcdda5 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -1489,7 +1489,7 @@
struct CountStackDepthVisitor : public StackVisitor {
CountStackDepthVisitor(const ManagedStack* stack,
const std::vector<TraceStackFrame>* trace_stack)
- : StackVisitor(stack, trace_stack), depth(0) {}
+ : StackVisitor(stack, trace_stack, NULL), depth(0) {}
bool VisitFrame() {
if (!GetMethod()->IsRuntimeMethod()) {
@@ -1499,6 +1499,7 @@
}
size_t depth;
};
+
CountStackDepthVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack());
visitor.WalkStack();
return visitor.depth;
@@ -1515,7 +1516,7 @@
public:
GetFrameVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
size_t start_frame, size_t frame_count, JDWP::ExpandBuf* buf)
- : StackVisitor(stack, trace_stack), depth_(0),
+ : StackVisitor(stack, trace_stack, NULL), depth_(0),
start_frame_(start_frame), frame_count_(frame_count), buf_(buf) {
expandBufAdd4BE(buf_, frame_count_);
}
@@ -1621,7 +1622,7 @@
struct FrameIdVisitor : public StackVisitor {
FrameIdVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
Method** m)
- : StackVisitor(stack, trace_stack), quick_frame_to_find(m) , frame_id(0) {}
+ : StackVisitor(stack, trace_stack, NULL), quick_frame_to_find(m) , frame_id(0) {}
virtual bool VisitFrame() {
if (quick_frame_to_find != GetCurrentQuickFrame()) {
@@ -1779,11 +1780,11 @@
void Dbg::SetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag,
uint64_t value, size_t width) {
struct SetLocalVisitor : public StackVisitor {
- SetLocalVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
+ SetLocalVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack, Context* context,
JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag, uint64_t value,
size_t width)
- : StackVisitor(stack, trace_stack), frame_id_(frame_id), slot_(slot), tag_(tag),
- value_(value), width_(width) {}
+ : StackVisitor(stack, trace_stack, context),
+ frame_id_(frame_id), slot_(slot), tag_(tag), value_(value), width_(width) {}
bool VisitFrame() {
if (GetFrameId() != frame_id_) {
@@ -1841,8 +1842,9 @@
const size_t width_;
};
Thread* thread = DecodeThread(threadId);
- SetLocalVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), frameId, slot, tag,
- value, width);
+ UniquePtr<Context> context(Context::Create());
+ SetLocalVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), context.get(),
+ frameId, slot, tag, value, width);
visitor.WalkStack();
}
@@ -2060,7 +2062,7 @@
struct SingleStepStackVisitor : public StackVisitor {
SingleStepStackVisitor(const ManagedStack* stack,
const std::vector<TraceStackFrame>* trace_stack)
- : StackVisitor(stack, trace_stack) {
+ : StackVisitor(stack, trace_stack, NULL) {
MutexLock mu(gBreakpointsLock); // Keep GCC happy.
gSingleStepControl.method = NULL;
gSingleStepControl.stack_depth = 0;
@@ -2955,7 +2957,7 @@
struct AllocRecordStackVisitor : public StackVisitor {
AllocRecordStackVisitor(const ManagedStack* stack,
const std::vector<TraceStackFrame>* trace_stack, AllocRecord* record)
- : StackVisitor(stack, trace_stack), record(record), depth(0) {}
+ : StackVisitor(stack, trace_stack, NULL), record(record), depth(0) {}
bool VisitFrame() {
if (depth >= kMaxAllocRecordStackDepth) {