From 04ad59de768b69b4e897a93f46efad9cc25737ad Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Sat, 12 Apr 2025 07:20:19 +0000 Subject: [PATCH] 8316397: StackTrace/Suspended/GetStackTraceSuspendedStressTest.java failed with: SingleStep event is NOT expected Reviewed-by: dholmes, pchilanomate --- src/hotspot/share/prims/jvmtiExport.cpp | 10 ++++++++-- src/hotspot/share/prims/jvmtiExport.hpp | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index d288baaab54..32dd6fc13e7 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -418,10 +418,16 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) { } JvmtiThreadState* -JvmtiExport::get_jvmti_thread_state(JavaThread *thread) { +JvmtiExport::get_jvmti_thread_state(JavaThread *thread, bool allow_suspend) { assert(thread == JavaThread::current(), "must be current thread"); if (thread->is_vthread_mounted() && thread->jvmti_thread_state() == nullptr) { JvmtiEventController::thread_started(thread); + if (allow_suspend && thread->is_suspended()) { + // Suspend here if thread_started got a suspend request during its execution. + // Within thread_started we could block on a VM mutex and pick up a suspend + // request from debug agent which we need to honor before proceeding. + ThreadBlockInVM tbivm(thread, true /* allow suspend */); + } } return thread->jvmti_thread_state(); } @@ -2636,7 +2642,7 @@ void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* na // jvmti thread state. // The collector and/or state might be null if JvmtiDynamicCodeEventCollector // has been initialized while JVMTI_EVENT_DYNAMIC_CODE_GENERATED was disabled. - JvmtiThreadState *state = get_jvmti_thread_state(thread); + JvmtiThreadState *state = get_jvmti_thread_state(thread, false /* allow_suspend */); if (state != nullptr) { JvmtiDynamicCodeEventCollector *collector = state->get_dynamic_code_event_collector(); if (collector != nullptr) { diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp index 324e437411a..e47cd3d6363 100644 --- a/src/hotspot/share/prims/jvmtiExport.hpp +++ b/src/hotspot/share/prims/jvmtiExport.hpp @@ -309,7 +309,11 @@ class JvmtiExport : public AllStatic { // If the jvmti_thread_state is absent and any thread filtered event // is enabled globally then it is created. // Otherwise, the thread->jvmti_thread_state() is returned. - static JvmtiThreadState* get_jvmti_thread_state(JavaThread *thread); + // The 'allow_suspend' parameter is passed as 'true' by default which work for almost all call sites. + // It means that a suspend point need to be organized by this function for virtual threads if the call + // to jvmtiEventController::thread_started hits a safepoint and gets a new suspend request. + // The 'allow_suspend' parameter must be passed as 'false' if thread is holding a VM lock. + static JvmtiThreadState* get_jvmti_thread_state(JavaThread *thread, bool allow_suspend = true); // single stepping management methods static void at_single_stepping_point(JavaThread *thread, Method* method, address location) NOT_JVMTI_RETURN;