Add the missing link between compiled code and the debugger.
When a debugger connects and disconnects, we now let compiled code know that we
need to be kept informed about what's going on.
Also fix a threading bug when threads exit with a debugger attached.
Also some minor tidying, mostly involving naming.
Change-Id: Iba0e8b9d192ac76ba1cd29a8b1e6d94f6f20dea8
diff --git a/src/debugger.cc b/src/debugger.cc
index 71776ae..569ea81 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -149,10 +149,10 @@
// JDWP is allowed unless the Zygote forbids it.
static bool gJdwpAllowed = true;
-// Was there a -Xrunjdwp or -agent argument on the command-line?
+// Was there a -Xrunjdwp or -agentlib:jdwp= argument on the command line?
static bool gJdwpConfigured = false;
-// Broken-down JDWP options. (Only valid if gJdwpConfigured is true.)
+// Broken-down JDWP options. (Only valid if IsJdwpConfigured() is true.)
static JDWP::JdwpOptions gJdwpOptions;
// Runtime JDWP state.
@@ -396,7 +396,7 @@
}
void Dbg::StartJdwp() {
- if (!gJdwpAllowed || !gJdwpConfigured) {
+ if (!gJdwpAllowed || !IsJdwpConfigured()) {
// No JDWP for you!
return;
}
@@ -477,6 +477,16 @@
return gDisposed;
}
+static void SetDebuggerUpdatesEnabledCallback(Thread* t, void* user_data) {
+ t->SetDebuggerUpdatesEnabled(*reinterpret_cast<bool*>(user_data));
+}
+
+static void SetDebuggerUpdatesEnabled(bool enabled) {
+ Runtime* runtime = Runtime::Current();
+ ScopedThreadListLock thread_list_lock;
+ runtime->GetThreadList()->ForEach(SetDebuggerUpdatesEnabledCallback, &enabled);
+}
+
void Dbg::GoActive() {
// Enable all debugging features, including scans for breakpoints.
// This is a no-op if we're already active.
@@ -487,29 +497,33 @@
LOG(INFO) << "Debugger is active";
- // TODO: CHECK we don't have any outstanding breakpoints.
+ {
+ // TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected?
+ MutexLock mu(gBreakpointsLock);
+ CHECK_EQ(gBreakpoints.size(), 0U);
+ }
gDebuggerActive = true;
-
- //dvmEnableAllSubMode(kSubModeDebuggerActive);
+ SetDebuggerUpdatesEnabled(true);
}
void Dbg::Disconnected() {
CHECK(gDebuggerConnected);
- gDebuggerActive = false;
+ LOG(INFO) << "Debugger is no longer active";
- //dvmDisableAllSubMode(kSubModeDebuggerActive);
+ gDebuggerActive = false;
+ SetDebuggerUpdatesEnabled(false);
gRegistry->Clear();
gDebuggerConnected = false;
}
-bool Dbg::IsDebuggerConnected() {
+bool Dbg::IsDebuggerActive() {
return gDebuggerActive;
}
-bool Dbg::IsDebuggingEnabled() {
+bool Dbg::IsJdwpConfigured() {
return gJdwpConfigured;
}
@@ -1379,7 +1393,6 @@
case Thread::kTimedWaiting: *pThreadStatus = JDWP::TS_WAIT; break;
case Thread::kBlocked: *pThreadStatus = JDWP::TS_MONITOR; break;
case Thread::kWaiting: *pThreadStatus = JDWP::TS_WAIT; break;
- case Thread::kInitializing: *pThreadStatus = JDWP::TS_ZOMBIE; break;
case Thread::kStarting: *pThreadStatus = JDWP::TS_ZOMBIE; break;
case Thread::kNative: *pThreadStatus = JDWP::TS_RUNNING; break;
case Thread::kVmWait: *pThreadStatus = JDWP::TS_WAIT; break;
@@ -1736,7 +1749,7 @@
}
void Dbg::PostException(Method** sp, Method* throwMethod, uintptr_t throwNativePc, Method* catchMethod, uintptr_t catchNativePc, Object* exception) {
- if (!gDebuggerActive) {
+ if (!IsDebuggerActive()) {
return;
}
@@ -1765,7 +1778,7 @@
}
void Dbg::PostClassPrepare(Class* c) {
- if (!gDebuggerActive) {
+ if (!IsDebuggerActive()) {
return;
}
@@ -1778,7 +1791,7 @@
}
void Dbg::UpdateDebugger(int32_t dex_pc, Thread* self, Method** sp) {
- if (!gDebuggerActive || dex_pc == -2 /* fake method exit */) {
+ if (!IsDebuggerActive() || dex_pc == -2 /* fake method exit */) {
return;
}
@@ -2461,9 +2474,12 @@
}
void Dbg::PostThreadStartOrStop(Thread* t, uint32_t type) {
- if (gDebuggerActive) {
+ if (IsDebuggerActive()) {
JDWP::ObjectId id = gRegistry->Add(t->GetPeer());
gJdwpState->PostThreadChange(id, type == CHUNK_TYPE("THCR"));
+ // If this thread's just joined the party while we're already debugging, make sure it knows
+ // to give us updates when it's running.
+ t->SetDebuggerUpdatesEnabled(true);
}
Dbg::DdmSendThreadNotification(t, type);
}