8288703: GetThreadState returns 0 for virtual thread that has terminated

Reviewed-by: alanb, amenkov, cjplummer
This commit is contained in:
Serguei Spitsyn 2022-07-02 05:43:43 +00:00
parent cfc9a881af
commit 9515560c54
4 changed files with 50 additions and 6 deletions
src/hotspot/share/prims
test/hotspot/jtreg/serviceability/jvmti
thread/GetThreadState/thrstat03
vthread/SelfSuspendDisablerTest

@ -1320,12 +1320,12 @@ JvmtiEnvBase::get_threadOop_and_JavaThread(ThreadsList* t_list, jthread thread,
java_thread = get_JavaThread_or_null(thread_oop);
}
}
*jt_pp = java_thread;
*thread_oop_p = thread_oop;
if (java_lang_VirtualThread::is_instance(thread_oop) &&
!JvmtiEnvBase::is_vthread_alive(thread_oop)) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
*jt_pp = java_thread;
*thread_oop_p = thread_oop;
return JVMTI_ERROR_NONE;
}

@ -87,7 +87,7 @@ public class thrstat03 {
throw new Error("Unexpected: " + e);
}
if (!check(t, t.isVirtual() ? NOT_STARTED : ZOMBIE)) {
if (!check(t, ZOMBIE)) {
throw new RuntimeException();
}
}

@ -36,12 +36,18 @@ public class SelfSuspendDisablerTest {
System.loadLibrary("SelfSuspendDisablerTest");
}
// Tested JVM TI thread states
static final int NEW = 0; // No bits are set
static final int TERMINATED = 2; // JVMTI_THREAD_STATE_TERMINATED
static final int RUNNABLE = 5; // JVMTI_THREAD_STATE_ALIVE & JVMTI_THREAD_STATE_RUNNABLE
static final int SUSPENDED = 0x100005; // RUNNABLE & JVMTI_THREAD_STATE_SUSPENDED
native static boolean isSuspended(Thread thread);
native static void selfSuspend();
native static void resume(Thread thread);
native static void suspendAllVirtualThreads();
native static void resumeAllVirtualThreads();
native static int getThreadState(Thread thread);
private static void sleep(long millis) {
try {
@ -51,26 +57,57 @@ public class SelfSuspendDisablerTest {
}
}
private static void testJvmtiThreadState(Thread thread, int expectedState) {
String kindStr = thread.isVirtual()? "virtual " : "platform";
int state = getThreadState(thread);
System.out.printf("Expected %s thread state: %06X got: %06X\n",
kindStr, expectedState, state);
if (state != expectedState) {
throw new RuntimeException("Test FAILED: Unexpected thread state");
}
}
public static void main(String argv[]) throws Exception {
Thread t1 = Thread.ofPlatform().start(() -> {
Thread t1 = Thread.ofPlatform().factory().newThread(() -> {
testJvmtiThreadState(Thread.currentThread(), RUNNABLE);
selfSuspend();
});
Thread t2 = Thread.ofVirtual().start(() -> {
Thread t2 = Thread.ofVirtual().factory().newThread(() -> {
testJvmtiThreadState(Thread.currentThread(), RUNNABLE);
while(!isSuspended(t1)) {
Thread.yield();
}
Thread.yield(); // provoke unmount
testJvmtiThreadState(t1, SUSPENDED);
resume(t1);
testJvmtiThreadState(t1, RUNNABLE);
suspendAllVirtualThreads();
});
testJvmtiThreadState(t1, NEW);
testJvmtiThreadState(t2, NEW);
t1.start();
t2.start();
while(!isSuspended(t2)) {
sleep(100);
}
testJvmtiThreadState(t2, SUSPENDED);
resumeAllVirtualThreads();
t2.join();
t1.join();
testJvmtiThreadState(t1, TERMINATED);
testJvmtiThreadState(t2, TERMINATED);
}
}

@ -58,8 +58,15 @@ Java_SelfSuspendDisablerTest_resumeAllVirtualThreads(JNIEnv* jni, jclass cls) {
check_jvmti_status(jni, jvmti->ResumeAllVirtualThreads(0, NULL), "Error in ResumeAllVirtualThreads");
}
JNIEXPORT jint JNICALL
Java_SelfSuspendDisablerTest_getThreadState(JNIEnv* jni, jclass cls, jthread thread) {
jint state;
check_jvmti_status(jni, jvmti->GetThreadState(thread, &state), "Error in GetThreadState");
return state;
}
} // extern "C"
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {