-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8311218: fatal error: stuck in JvmtiVTMSTransitionDisabler::VTMS_transition_disable #17011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
👋 Welcome back sspitsyn! A progress list of the required criteria for merging this PR into |
|
@sspitsyn The following labels will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
|
@sspitsyn this pull request can not be integrated into git checkout b13
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
…o VirtualThread methods
|
I chatted briefly with @sspitsyn about this. A couple of points:
|
|
/label -build |
|
@magicus |
...ot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLock/SuspendWithInterruptLock.java
Show resolved
Hide resolved
...ot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLock/SuspendWithInterruptLock.java
Outdated
Show resolved
Hide resolved
| while (iterations-- > 0) { | ||
| Thread.yield(); | ||
| } | ||
| done = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to use done to stop all threads and set it to true in the main thread after some time. So you could be sure that the yielder hadn't been completed before the suspender started. But it is just proposal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. Will consider this.
src/hotspot/share/prims/jvm.cpp
Outdated
|
|
||
| // Notification from VirtualThread about entering/exiting sync critical section. | ||
| // Needed to avoid deadlocks with JVMTI suspend mechanism. | ||
| JVM_ENTRY(void, JVM_VirtualThreadCriticalLock(JNIEnv* env, jobject vthread, jboolean enter)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the jobject vthread is not used. Can't be the method made static to reduce the number of arguments?
It is the performance-critical code, I don't know if it is optimized by C2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question.
In general, I'd like to keep this unified with the other notiftJvmti methods.
Let me double check how it fits together.
Also, I'm not sure how is going to impact the intrinsification.
|
@AlanBateman Thank you for reviewing an the comment.
Carrier thread also can be suspended when executing the "critical code".
Is your concern a recursive
Right, thanks. It is already done.
Okay. What about the Leonid's suggestion to name it |
It's a different scenario. When mounting, the coordination of the interrupt status is done before the thread identity is changed. Similarly, when unmounting, the coordination is done after reverting the thread identity to the carrier. So if there is an agent randomly suspending threads when it shouldn't be an issue here.
Minimally an assert. A counter might be needed later.
We have changes in the works that require pinning during some critical sections so I think I prefer to use that terminology. We can move the notification to JVMTI to the enter/leave methods. |
Okay with me. We'll need to move the notifyJvmtiDisableSuspend(true) to before the try in all cases, I've pointed out the cases that we missed. |
Thank you, Alan. Fixed now. |
Thanks, it looks much better now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think okay, I don't have any other comments.
|
@sspitsyn This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 1 new commit pushed to the
Please see this link for an up-to-date comparison between the source branch of this pull request and the ➡️ To integrate this PR with the above commit message to the |
|
Alan and Leonid, thank you for review! |
|
/integrate |
|
Going to push as commit 0f8e4e0.
Your commit was automatically rebased without conflicts. |
| #else | ||
| fatal("Should only be called with JVMTI enabled"); | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't do this! The Java code knows nothing about JVM TI being enabled/disabled and will call this function unconditionally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't do this! The Java code knows nothing about JVM TI being enabled/disabled and will call this function unconditionally.
Indeed. I wonder if anyone is testing minimal builds to catch issues like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, David!
Filed a cleanup bug: https://bugs.openjdk.org/browse/JDK-8322538
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these new compiler intrinsics required or an optional performance optimization? This PR creates issues for us when updating the JDK build for Graal. CC @davleopo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these new compiler intrinsics required or an optional performance optimization?
Performance. If the intrinsic isn't there then some methods executed on virtual threads, or on a virtual thread as the target for some op, will have to call into the VM. The main concern was Thread.interrupted() as it gets called very frequently in locking and concurrency code.
| void toggle_is_in_tmp_VTMS_transition() { _is_in_tmp_VTMS_transition = !_is_in_tmp_VTMS_transition; }; | ||
|
|
||
| bool is_disable_suspend() const { return _is_disable_suspend; } | ||
| void toggle_is_disable_suspend() { _is_disable_suspend = !_is_disable_suspend; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this again then I don't think it can be a bit that is toggled on and off will work. Consider the case where several threads attempt to poll the state of a virtual Thread with Thread::getState at the same time. This can't work without an atomic counter and further coordination. So I think further work is required on this issue.
Update: ignore this I mis-read that it updates the current thread's suspend value, not the thread's suspend value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: ignore this I mis-read that it updates the current thread's suspend value, not the thread's suspend value.
Thanks, Alan. I've also got confused with this and even filed a follow up bug. :)
Yes, the initial design was the _is_disable_suspend is set/modified/accessed on the current thread only.
|
/backport jdk22 |
|
@sspitsyn the backport was successfully created on the branch backport-sspitsyn-0f8e4e0a in my personal fork of openjdk/jdk22. To create a pull request with this backport targeting openjdk/jdk22:master, just click the following link: The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:
If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk22: |
This fix is for JDK 23 but the intention is to back port it to 22 in RDP-1 time frame.
It is fixing a deadlock issue between
VirtualThreadclass critical sections with theinterruptLock(in methods:unpark(),interrupt(),getAndClearInterrupt(),threadState(),toString()),JvmtiVTMSTransitionDisablerand JVMTISuspend/Resumemechanisms.The deadlocking scenario is well described by Patricio in a bug report comment.
In simple words, a virtual thread should not be suspended during 'interruptLock' critical sections.
The fix is to record that a virtual thread is in a critical section (
JavaThread's_in_critical_sectionbit) by notifying the VM/JVMTI about begin/end of critical section.This bit is used in
HandshakeState::get_op_for_self()to filter out anyHandshakeOperationif a targetJavaThreadis in a critical section.Some of new notifications with
notifyJvmtiSync()method is on a performance critical path. It is why this method has been intrincified.New test was developed by Patricio:
test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLockThe test is very nice as it reliably in 100% reproduces the deadlock without the fix.
The test is never failing with this fix.
Testing:
test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLockProgress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/17011/head:pull/17011$ git checkout pull/17011Update a local copy of the PR:
$ git checkout pull/17011$ git pull https://git.openjdk.org/jdk.git pull/17011/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 17011View PR using the GUI difftool:
$ git pr show -t 17011Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/17011.diff
Webrev
Link to Webrev Comment