Skip to content

Commit 7ca753b

Browse files
committed
8269268: JDWP: Properly fix thread lookup assert in findThread()
Reviewed-by: kevinw, amenkov, sspitsyn
1 parent 7a23c9c commit 7ca753b

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,10 @@ cbVMDeath(jvmtiEnv *jvmti_env, JNIEnv *env)
12301230
EventInfo info;
12311231
LOG_CB(("cbVMDeath"));
12321232

1233+
/* Setting this flag is needed by findThread(). It's ok to set it before
1234+
the callbacks are cleared.*/
1235+
gdata->jvmtiCallBacksCleared = JNI_TRUE;
1236+
12331237
/* Clear out ALL callbacks at this time, we don't want any more. */
12341238
/* This should prevent any new BEGIN_CALLBACK() calls. */
12351239
(void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks));

src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,36 @@ findThread(ThreadList *list, jthread thread)
254254
node = nonTlsSearch(getEnv(), &otherThreads, thread);
255255
}
256256
/*
257-
* Search runningThreads list. The TLS lookup may have failed because the
258-
* thread has terminated, but the ThreadNode may still be present.
257+
* Normally we can assume that a thread with no TLS will never be in the runningThreads
258+
* list. This is because we always set the TLS when adding to runningThreads.
259+
* However, when a thread exits, its TLS is automatically cleared. Normally this
260+
* is not a problem because the debug agent will first get a THREAD_END event,
261+
* and that will cause the thread to be removed from runningThreads, thus we
262+
* avoid this situation of having a thread in runningThreads, but with no TLS.
263+
*
264+
* However... there is one exception to this. While handling VM_DEATH, the first thing
265+
* the debug agent does is clear all the callbacks. This means we will no longer
266+
* get THREAD_END events as threads exit. This means we might find threads on
267+
* runningThreads with no TLS during VM_DEATH. Essentially the THREAD_END that
268+
* would normally have resulted in removing the thread from runningThreads is
269+
* missed, so the thread remains on runningThreads.
270+
*
271+
* The end result of all this is that if the TLS lookup failed, we still need to check
272+
* if the thread is on runningThreads, but only if JVMTI callbacks have been cleared.
273+
* Otherwise the thread should not be on the runningThreads.
259274
*/
260-
if ( node == NULL ) {
261-
if ( list == NULL || list == &runningThreads ) {
262-
node = nonTlsSearch(getEnv(), &runningThreads, thread);
275+
if ( !gdata->jvmtiCallBacksCleared ) {
276+
/* The thread better not be on runningThreads if the TLS lookup failed. */
277+
JDI_ASSERT(!nonTlsSearch(getEnv(), &runningThreads, thread));
278+
} else {
279+
/*
280+
* Search the runningThreads list. The TLS lookup may have failed because the
281+
* thread has terminated, but we never got the THREAD_END event.
282+
*/
283+
if ( node == NULL ) {
284+
if ( list == NULL || list == &runningThreads ) {
285+
node = nonTlsSearch(getEnv(), &runningThreads, thread);
286+
}
263287
}
264288
}
265289
}

src/jdk.jdwp.agent/share/native/libjdwp/util.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,11 @@ typedef struct {
133133
int objectsByIDsize;
134134
int objectsByIDcount;
135135

136-
/* Indication that the agent has been loaded */
137-
jboolean isLoaded;
136+
/* Indication that the agent has been loaded */
137+
jboolean isLoaded;
138+
139+
/* Indication that VM_DEATH has been recieved and the JVMTI callbacks have been cleared. */
140+
volatile jboolean jvmtiCallBacksCleared;
138141

139142
} BackendGlobalData;
140143

0 commit comments

Comments
 (0)