Fix debugger to properly return TS_SLEEPING.
Thread.sleep is implemented with Object.wait, so the code can't
distinguish the two. I added a check to see if Thread.sleep
is somewhere on the stack, indicating that the thread is actually
sleeping instead of waiting.
Change-Id: I288befc1b3dc76e30c0620ab9c850c66b81c7a6d
diff --git a/src/debugger.cc b/src/debugger.cc
index 77a9252..158be0b 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -1420,8 +1420,6 @@
MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_);
- // TODO: if we're in Thread.sleep(long), we should return TS_SLEEPING,
- // even if it's implemented using Object.wait(long).
switch (thread->GetState()) {
case kTerminated: *pThreadStatus = JDWP::TS_ZOMBIE; break;
case kRunnable: *pThreadStatus = JDWP::TS_RUNNING; break;
@@ -1444,6 +1442,34 @@
// Don't add a 'default' here so the compiler can spot incompatible enum changes.
}
+ if (thread->GetState() == kTimedWaiting) {
+ // Since Thread.sleep is implemented using Object.wait, see if Thread.sleep
+ // is on the stack and change state to TS_SLEEPING if it is.
+ struct SleepMethodVisitor : public StackVisitor {
+ SleepMethodVisitor(const ManagedStack* stack,
+ const std::deque<InstrumentationStackFrame>* instrumentation_stack)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : StackVisitor(stack, instrumentation_stack, NULL), found_(false) {}
+
+ virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ std::string name(PrettyMethod(GetMethod(), false));
+ if (name == "java.lang.Thread.sleep") {
+ found_ = true;
+ return false;
+ }
+ return true;
+ }
+
+ bool found_;
+ };
+
+ SleepMethodVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack());
+ visitor.WalkStack(false);
+ if (visitor.found_) {
+ *pThreadStatus = JDWP::TS_SLEEPING;
+ }
+ }
+
*pSuspendStatus = (thread->IsSuspended() ? JDWP::SUSPEND_STATUS_SUSPENDED : JDWP::SUSPEND_STATUS_NOT_SUSPENDED);
return true;