diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c index 491182a583feb..394071338896e 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c @@ -157,11 +157,20 @@ setThreadLocalStorage(jthread thread, ThreadNode *node) error = JVMTI_FUNC_PTR(gdata->jvmti,SetThreadLocalStorage) (gdata->jvmti, thread, (void*)node); - if ( error == JVMTI_ERROR_THREAD_NOT_ALIVE && node == NULL) { - /* Just return. This can happen when clearing the TLS. */ - return; - } else if ( error != JVMTI_ERROR_NONE ) { - /* The jthread object must be valid, so this must be a fatal error */ + if (error == JVMTI_ERROR_THREAD_NOT_ALIVE) { + if (node == NULL) { + // Just return. This can happen when clearing the TLS. + return; + } + if (isVThread(thread)) { + // Just return. This can happen with a vthread that is running and we + // had to create a ThreadNode for it. By the time we get here, it may + // have already terminated. + return; + } + } + if (error != JVMTI_ERROR_NONE) { + // The jthread object must be valid, so this must be a fatal error. EXIT_ERROR(error, "cannot set thread local storage"); } } @@ -251,9 +260,10 @@ findThread(ThreadList *list, jthread thread) * Otherwise the thread should not be on the runningThreads. */ if ( !gdata->jvmtiCallBacksCleared ) { - /* The thread better not be on either list if the TLS lookup failed. */ + // The thread better not be on the runningThreads list if the TLS lookup failed. + // It might be on the runningVThreads list because of how ThreadNodes for vthreads + // can be recreated just before terminating, so we don't check runningVThreads. JDI_ASSERT(!nonTlsSearch(getEnv(), &runningThreads, thread)); - JDI_ASSERT(!nonTlsSearch(getEnv(), &runningVThreads, thread)); } else { /* * Search the runningThreads and runningVThreads lists. The TLS lookup may have