-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8361912: ThreadsListHandle::cv_internal_thread_to_JavaThread does not deal with a virtual thread's carrier thread #26287
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
for virtual threads, and add a new oop variant.
👋 Welcome back dholmes! A progress list of the required criteria for merging this PR into |
@dholmes-ora 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 201 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
@dholmes-ora 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. |
…ew API" This reverts commit 4ed9035.
Webrevs
|
I still think that it would be safer to explicitly specify that caller knows that jthread can be virtual thread (and maybe add assert when a caller works only with platform threads, but passed jthread is virtual), but ok, it's up to you. |
I think that retains the risk of the caller not knowing they need to ensure they protect the carrier thread.
No, we had some internal discussions and that code is incorrectly using the JVMTI transition disabler, so it needs a complete overhaul. That will be handled separately. Thanks again for looking at this in depth Alex. |
java_thread = java_lang_Thread::thread(carrier_thread); | ||
} | ||
if (java_thread == nullptr) { | ||
// Virtual thread was unmounted, or else carrier has now terminated. |
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.
Nit: If java_thread
for a virtual thread is null then this thread is unmounted. The words about the terminated carrier thread are confusing.
I have one concern here. Nothing protects this code from facing some unexpected conditions as this function is racy with mounting and unmounting of target virtual thread
- this function can observe a
JavaThread
inmount
orunmount
transition where the thread identity of ajava.lang.Thread
associated with theJavaThread
is not consistent (in a VTMS transition the thread identity might not match the stack trace) - nothing guaranties that the result returned by this function remains the same upon return as
mount
/unmount
of the target virtual thread can be executed concurrently: a mounted virtual thread can be quickly unmounted or an unmounted virtual thread can be quickly mounted
So, it seems that this function is going to work correctly if used for target platform threads only or if the JavaThread*
pointer is not really needed. Otherwise, the association with the JavaThread
needs to be rechecked and its stability somehow guaranteed with any form of scheduling suspension or a VTMS transition disabler.
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 java_thread can be null because the carrier of a mounted vthread was not contained in the ThreadsListHandle.
The only thing this function guarantees is that if the vthread appeared to have a carrier and that carrier is protected by the TLH, then the caller can safely interact with the carrier knowing it can't terminate - same as for regular threads. The caller has to account for the potential async mounting/unmounting of vthread - e.g. by handshaking the reported carrier and then confirming it is still the carrier.
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.
Note that java_thread
may already be null so we don't get to execute line 836.
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.
Thanks, David. The potential issue I'm still concerned about is that a subsequent handshaking can also observe the JavaThread (and virtual thread as well) in a VTMS transition when there is no protection with a VTMSTransitionDisabler
.
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.
Note that java_thread may already be null so we don't get to execute line 836.
Right. I guess, this answers my comment about the line 839.
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.
Okay, thanks.
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.
Once this change is in main line then we can sync'up the loom repo and work on the follow-up changes. The loom repo has changes (that are not in main line) for "suspending" an unmounted thread. For the mounted case then we'll need checks in the handshake to ensure that the expected virtual threads is mounted. We'll need stress tests of course and we can collaborate there in advance of proposing changes for main line.
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.
Note that java_thread may already be null so we don't get to execute line 836.
I'm having some trouble with this statement. Working backwards from L836, I see
the nullptr check on L826 and the check for non-virtual thread and bail on L827
and L831. However, if we saw nullptr on L826 and we have a virtual thread, then
we can get to L836 even when we started off with a null java_thread.
So I guess I'm not sure what point you're trying to make with the statement.
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.
then we can get to L836 even when we started off with a null java_thread.
Sure. My point was more the other way round - we could have a null JavaThread without the null coming from line 836.
The comment was just trying to expand on my previous comment.
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.
Thanks for the clarification.
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.
This looks okay to me.
Thanks for the review @sspitsyn ! |
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.
LGTM.
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.
Thumbs up on the changes. I think I only have a few nits.
java_thread = java_lang_Thread::thread(carrier_thread); | ||
} | ||
if (java_thread == nullptr) { | ||
// Virtual thread was unmounted, or else carrier has now terminated. |
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.
Note that java_thread may already be null so we don't get to execute line 836.
I'm having some trouble with this statement. Working backwards from L836, I see
the nullptr check on L826 and the check for non-virtual thread and bail on L827
and L831. However, if we saw nullptr on L826 and we have a virtual thread, then
we can get to L836 even when we started off with a null java_thread.
So I guess I'm not sure what point you're trying to make with the statement.
Thanks for the review @dcubed-ojdk ! Just need one Reviewer to re-review the nit fix-ups. Thanks |
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.
Thanks for the updates. Thumbs up.
Thanks Dan! /integrate |
Going to push as commit 4669005.
Your commit was automatically rebased without conflicts. |
@dholmes-ora Pushed as commit 4669005. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
The
cv_internal_thread_to_JavaThread
method will now check if the thread is a mounted virtual thread, and if so protect the carrier thread. User's of the API that need to deal with virtual threads must still check the carrier themselves as it could change asynchronously, but it is now guaranteed that the carrier JavaThread returned via this method cannot terminate whilst being used (the same as regular platform JavaThreads).It was noticed whilst updating the documentation that the
JvmtiExport
variantcv_oop_to_JavaThread
is unused and so can be removed.Testing:
Thanks
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/26287/head:pull/26287
$ git checkout pull/26287
Update a local copy of the PR:
$ git checkout pull/26287
$ git pull https://git.openjdk.org/jdk.git pull/26287/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 26287
View PR using the GUI difftool:
$ git pr show -t 26287
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/26287.diff
Using Webrev
Link to Webrev Comment