summaryrefslogtreecommitdiffstats
path: root/runtime/thread.cc
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2015-06-01 17:33:12 +0200
committerSebastien Hertz <shertz@google.com>2015-06-12 12:46:49 +0200
commit6ba35b50347aa7418c66c7b046cd164987e95df3 (patch)
tree16a56b28351cd5c8459d6ea82306503c7ebe7cbe /runtime/thread.cc
parentc72c5ac9d9e16ebf262f0dd75e9686a3e1d67bd9 (diff)
downloadart-6ba35b50347aa7418c66c7b046cd164987e95df3.tar.gz
art-6ba35b50347aa7418c66c7b046cd164987e95df3.tar.bz2
art-6ba35b50347aa7418c66c7b046cd164987e95df3.zip
JDWP: asynchronous invoke command handling
The JDWP thread used to wait for the result of a method invocation running in an event thread. But doing that prevents the JDWP thread from processing incoming commands from the debugger if the event thread gets suspended by a debug event occurring in another thread. In Android Studio (or another IDE), this leads to the debugger being blocked (with the famous message "Waiting until last debugger command completes" of Android Studio / IntelliJ) because it is actually waiting for the reply of its latest command while the JDWP thread cannot process it. This CL changes the way invoke commands (ClassType.InvokeCommand, ClassType.NewInstance and ObjectReference.InvokeCommand) are handled in the ART runtime. The JDWP thread no longer waits for the event thread to complete the method invocation. It now simply waits for the next JDWP command to process. This means it does not send any reply for invoke commands, except if the information given by the debugger is wrong. In this case, it still sends a reply with the appropriate error code. The event thread is now responsible for sending the reply (containing the result and the exception object of the invoked method) before going back to the suspended state. In other words, we add special handling for invoke commands so they are handled asynchronously while other commands remained handled synchronously. In the future, we may want to handle all commands asynchronously (using a queue of reply/event for instance) to remove the special handling code this CL is adding. Now the JDWP thread can process commands while a thread is invoking a method, it is possible for the debugger to detach (by sending a VirtualMachine.Dispose command) before the invocation completes. In that situation, we must not suspend threads again (including the event thread that executed the method) because they would all remain suspended forever. Also minor cleanup of the use of JDWP constants and update comments. Bug: 21515842 Bug: 18899981 (cherry picked from commit cbc5064ff05179b97b416f00ca579c55e38cd7d9) Change-Id: I8d31006043468913ee8453212e6d16e11fcfe4ea
Diffstat (limited to 'runtime/thread.cc')
-rw-r--r--runtime/thread.cc5
1 files changed, 2 insertions, 3 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 845345ad61..29635a4308 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2517,12 +2517,11 @@ void Thread::SetDebugInvokeReq(DebugInvokeReq* req) {
}
void Thread::ClearDebugInvokeReq() {
- CHECK(Dbg::IsDebuggerActive());
CHECK(GetInvokeReq() != nullptr) << "Debug invoke req not active in thread " << *this;
CHECK(Thread::Current() == this) << "Debug invoke must be finished by the thread itself";
- // We do not own the DebugInvokeReq* so we must not delete it, it is the responsibility of
- // the owner (the JDWP thread).
+ DebugInvokeReq* req = tlsPtr_.debug_invoke_req;
tlsPtr_.debug_invoke_req = nullptr;
+ delete req;
}
void Thread::PushVerifier(verifier::MethodVerifier* verifier) {