summaryrefslogtreecommitdiffstats
path: root/vm/Debugger.c
diff options
context:
space:
mode:
authorAndy McFadden <fadden@android.com>2009-10-13 16:04:31 -0700
committerAndy McFadden <fadden@android.com>2009-10-13 16:04:31 -0700
commit0d6fff2da41e53c3ee790f352a40e84ad782d286 (patch)
treefbfdcd5bf977247a1e1720ef596ed3c7bfbe0840 /vm/Debugger.c
parent6ff3c8fde9623dadad726dbd5e1658585c321751 (diff)
downloadandroid_dalvik-0d6fff2da41e53c3ee790f352a40e84ad782d286.tar.gz
android_dalvik-0d6fff2da41e53c3ee790f352a40e84ad782d286.tar.bz2
android_dalvik-0d6fff2da41e53c3ee790f352a40e84ad782d286.zip
Avoid JDWP hang on nested thread suspension.
With jdb, you can suspend a thread multiple times. If you try to execute a method -- which requires resuming a thread that has been stopped at a breakpoint -- the VM currently only does a single "resume", which means the thread is still suspended, and the JDWP thread hangs waiting for it. This adds a check to prevent the hang. For bug 2183735.
Diffstat (limited to 'vm/Debugger.c')
-rw-r--r--vm/Debugger.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/vm/Debugger.c b/vm/Debugger.c
index 86adbb671..eec8176cc 100644
--- a/vm/Debugger.c
+++ b/vm/Debugger.c
@@ -2698,6 +2698,30 @@ JdwpError dvmDbgInvokeMethod(ObjectId threadId, ObjectId objectId,
}
/*
+ * We currently have a bug where we don't successfully resume the
+ * target thread if the suspend count is too deep. We're expected to
+ * require one "resume" for each "suspend", but when asked to execute
+ * a method we have to resume fully and then re-suspend it back to the
+ * same level. (The easiest way to cause this is to type "suspend"
+ * multiple times in jdb.)
+ *
+ * It's unclear what this means when the event specifies "resume all"
+ * and some threads are suspended more deeply than others. This is
+ * a rare problem, so for now we just prevent it from hanging forever
+ * by rejecting the method invocation request. Without this, we will
+ * be stuck waiting on a suspended thread.
+ */
+ if (targetThread->suspendCount > 1) {
+ LOGW("threadid=%d: suspend count on threadid=%d is %d, too deep "
+ "for method exec\n",
+ dvmThreadSelf()->threadId, targetThread->threadId,
+ targetThread->suspendCount);
+ err = ERR_THREAD_SUSPENDED; /* probably not expected here */
+ dvmUnlockThreadList();
+ goto bail;
+ }
+
+ /*
* TODO: ought to screen the various IDs, and verify that the argument
* list is valid.
*/