Skip to content
Permalink
Browse files
fixed issue in JVMTI SuspendThread when JavaThread suspends itself
  • Loading branch information
sspitsyn committed Mar 24, 2021
1 parent c6f8b02 commit 25aaf9e897ac914836248e29365da6e0ea820fac
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 10 deletions.
@@ -226,6 +226,7 @@ JvmtiVTMTDisabler::disable_VTMT() {
while (_VTMT_count > 0) {
ml.wait();
}
thread->set_is_VTMT_disabler(true);
}

void
@@ -236,6 +237,14 @@ JvmtiVTMTDisabler::enable_VTMT() {
if (--_VTMT_disable_count == 0) {
ml.notify_all();
}
JavaThread* thread = JavaThread::current();
thread->set_is_VTMT_disabler(false);

// A JavaThread disabling VTMT can't suspend itself without deadlock.
// It is self-suspended here after VTMT has been enabled again.
while (thread->is_external_suspend()) {
ml.wait();
}
}

void
@@ -1195,6 +1195,7 @@ JavaThread::JavaThread() :
_doing_unsafe_access(false),
_do_not_unlock_if_synchronized(false),
_is_in_VTMT(false),
_is_VTMT_disabler(false),
_jni_attach_state(_not_attaching_via_jni),
#if INCLUDE_JVMCI
_pending_deoptimization(-1),
@@ -1865,7 +1866,9 @@ void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) {
void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) {

// Check for pending external suspend.
if (is_external_suspend_with_lock()) {
// A JavaThread disabling VTMT can't be suspended without deadlock.
// It will be self-suspended after VTMT is reenabled.
if (!is_VTMT_disabler() && is_external_suspend_with_lock()) {
frame_anchor()->make_walkable(this);
java_suspend_self_with_safepoint_check();
}
@@ -1959,7 +1962,9 @@ void JavaThread::java_suspend() {
}

{ MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
if (!is_external_suspend()) {
// A JavaThread disabling VTMT can't be suspended without deadlock.
// It will be self-suspended after VTMT is reenabled.
if (is_VTMT_disabler() || !is_external_suspend()) {
// a racing resume has cancelled us; bail out now
return;
}
@@ -2041,6 +2046,7 @@ int JavaThread::java_suspend_self() {

// _ext_suspended flag is cleared by java_resume()
while (is_ext_suspended()) {
assert(!is_VTMT_disabler(), "sanity check");
ml.wait();
}
}
@@ -988,6 +988,7 @@ class JavaThread: public Thread {
bool _do_not_unlock_if_synchronized; // Do not unlock the receiver of a synchronized method (since it was
// never locked) when throwing an exception. Used by interpreter only.
bool _is_in_VTMT; // thread is in virtual thread mount transition
bool _is_VTMT_disabler; // thread currently disabled VTMT

// JNI attach states:
enum JNIAttachStates {
@@ -1355,6 +1356,8 @@ class JavaThread: public Thread {

bool is_in_VTMT() const { return _is_in_VTMT; }
void set_is_in_VTMT(bool val) { _is_in_VTMT = val; }
bool is_VTMT_disabler() const { return _is_VTMT_disabler; }
void set_is_VTMT_disabler(bool val) { _is_VTMT_disabler = val; }

// Thread.stop support
void send_thread_stop(oop throwable);
@@ -25,26 +25,26 @@
#include "jvmti.h"
#include "jvmti_common.h"

static jvmtiEnv *jvmti_env = NULL;
static jvmtiEnv *jvmti = NULL;

extern "C" {

JNIEXPORT void JNICALL
Java_SelfSuspendDisablerTest_resume(JNIEnv* jni, jclass cls,jthread thread) {
check_jvmti_status(jni, jvmti_env->ResumeThread(thread), "Error in ResumeThread");
check_jvmti_status(jni, jvmti->ResumeThread(thread), "Error in ResumeThread");
}

JNIEXPORT void JNICALL
Java_SelfSuspendDisablerTest_selfSuspend(JNIEnv* jni, jclass cls) {
jthread thread;
check_jvmti_status(jni, jvmti_env->GetCurrentThread(&thread), "Error in CurrentThread");
check_jvmti_status(jni, jvmti_env->SuspendThread(thread), "Error in SuspendThread");
check_jvmti_status(jni, jvmti->GetCurrentThread(&thread), "Error in CurrentThread");
check_jvmti_status(jni, jvmti->SuspendThread(thread), "Error in SuspendThread");
}

JNIEXPORT jboolean JNICALL
Java_SelfSuspendDisablerTest_isSuspended(JNIEnv* jni, jclass cls, jthread thread) {
jint state;
check_jvmti_status(jni, jvmti_env->GetThreadState(thread, &state), "Error in GetThreadState");
check_jvmti_status(jni, jvmti->GetThreadState(thread, &state), "Error in GetThreadState");
return (state & JVMTI_THREAD_STATE_SUSPENDED) != 0;
}

@@ -56,7 +56,7 @@ jint Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {

printf("Agent init started\n");

if (jvm->GetEnv((void **)(&jvmti_env), JVMTI_VERSION) != JNI_OK) {
if (jvm->GetEnv((void **)(&jvmti), JVMTI_VERSION) != JNI_OK) {
printf("Agent init: error in getting JvmtiEnv with GetEnv\n");
return JNI_ERR;
}
@@ -65,10 +65,11 @@ jint Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
memset(&caps, 0, sizeof(caps));
caps.can_suspend = 1;

err = jvmti_env->AddCapabilities(&caps);
err = jvmti->AddCapabilities(&caps);
if (err != JVMTI_ERROR_NONE) {
return JNI_ERR;
}

printf("Agent init finished\n");
return JNI_OK;
}
}

0 comments on commit 25aaf9e

Please sign in to comment.