RFR: 8364314: java_lang_Thread::get_thread_status fails assert(base != nullptr) failed: Invalid base [v2]
Daniel D. Daugherty
dcubed at openjdk.org
Wed Jul 30 17:31:55 UTC 2025
On Wed, 30 Jul 2025 06:24:39 GMT, David Holmes <dholmes at openjdk.org> wrote:
>> After the changes in JDK-8361912 we could "return " the carrier thread from `cv_internal_thread_to_JavaThread`, but before we hit the transition disabler the virtual thread could unmount. As a result when we execute this code:
>>
>> if (is_virtual) {
>> // 1st need to disable mount/unmount transitions
>> transition_disabler.init(jthread);
>>
>> carrier_thread = Handle(THREAD, java_lang_VirtualThread::carrier_thread(thread_h()));
>> if (carrier_thread != nullptr) {
>> java_thread = java_lang_Thread::thread(carrier_thread());
>> }
>> }
>>
>> we hit the implicit else where "`carrier_thread == nullptr`" and we do nothing, but `java_thread` still holds the old carrier, which we then perform the handshake operation with:
>>
>> void do_thread(Thread* th) override {
>> Thread* current = Thread::current();
>>
>> bool is_virtual = java_lang_VirtualThread::is_instance(_thread_h());
>> if (_java_thread != nullptr) {
>> if (is_virtual) {
>> // mounted vthread, use carrier thread state
>> oop carrier_thread = java_lang_VirtualThread::carrier_thread(_thread_h());
>> _thread_status = java_lang_Thread::get_thread_status(carrier_thread);
>> } else {
>>
>> But the `_java_thread` no longer has a carrier, so `get_thread_status` is passed null and we crash.
>>
>> Simple fix is to clear `java_thread` when we find a null carrier oop. Also added an assert to guard against a null carrier oop in the handshake code, and added some additional commentary.
>>
>> Testing:
>> - com/sun/management/HotSpotDiagnosticMXBean/DumpThreads.java
>> - tier 5 and 6
>>
>> Thanks
>
> David Holmes has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains three additional commits since the last revision:
>
> - Remove from ProblemList
> - Merge branch 'master' into 8364314-threadSMR
> - 8364314: java_lang_Thread::get_thread_status fails assert(base != nullptr) failed: Invalid base
In src/hotspot/share/prims/whitebox.cpp, we have three functions:
- WB_HandshakeReadMonitors
- WB_HandshakeWalkStack
- WB_AsyncHandshakeWalkStack
that call `tlh.cv_internal_thread_to_JavaThread` and each of them
does a handshake operation with the 'target' thread. If the `target`
is a virtual thread, then we'll do the handshake with the carrier thread
and not with the virtual thread. None of these functions in whitebox.cpp
use a JvmtiVTMSTransitionDisabler to prevent the virtual thread from
being unmounted from the carrier thread. I could be missing it, but I
don't see a way that the virtual thread info that _should be_ mounted
on the carrier thread is being passed to the handshake code. So what
does the handshake code do when it gets down into the guts and
the carrier thread no longer has a virtual thread mounted on it or if
a different virtual thread is mounted on it?
I'm not sure who to ping for answering this query.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/26544#issuecomment-3137238546
More information about the hotspot-runtime-dev
mailing list