8306324: StopThread results in thread being marked as interrupted, leading to unexpected InterruptedException

Reviewed-by: pchilanomate, alanb
This commit is contained in:
Serguei Spitsyn 2025-08-02 04:21:42 +00:00
parent 7ea08d3928
commit e801e51311
3 changed files with 10 additions and 10 deletions

View File

@ -2880,15 +2880,16 @@ JVM_ENTRY(void, JVM_SleepNanos(JNIEnv* env, jclass threadClass, jlong nanos))
} else {
ThreadState old_state = thread->osthread()->get_state();
thread->osthread()->set_state(SLEEPING);
if (!thread->sleep_nanos(nanos)) { // interrupted
if (!thread->sleep_nanos(nanos)) { // interrupted or async exception was installed
// An asynchronous exception could have been thrown on
// us while we were sleeping. We do not overwrite those.
if (!HAS_PENDING_EXCEPTION) {
HOTSPOT_THREAD_SLEEP_END(1);
// TODO-FIXME: THROW_MSG returns which means we will not call set_state()
// to properly restore the thread state. That's likely wrong.
THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
if (!thread->has_async_exception_condition()) {
// TODO-FIXME: THROW_MSG returns which means we will not call set_state()
// to properly restore the thread state. That's likely wrong.
THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
}
}
}
thread->osthread()->set_state(old_state);

View File

@ -1146,7 +1146,6 @@ void JavaThread::install_async_exception(AsyncExceptionHandshakeClosure* aehc) {
oop vt_oop = vthread();
if (vt_oop == nullptr || !vt_oop->is_a(vmClasses::BaseVirtualThread_klass())) {
// Interrupt thread so it will wake up from a potential wait()/sleep()/park()
java_lang_Thread::set_interrupted(threadObj(), true);
this->interrupt();
}
}
@ -2098,7 +2097,7 @@ bool JavaThread::sleep(jlong millis) {
// java.lang.Thread.sleep support
// Returns true if sleep time elapsed as expected, and false
// if the thread was interrupted.
// if the thread was interrupted or async exception was installed.
bool JavaThread::sleep_nanos(jlong nanos) {
assert(this == Thread::current(), "thread consistency check");
assert(nanos >= 0, "nanos are in range");
@ -2118,6 +2117,9 @@ bool JavaThread::sleep_nanos(jlong nanos) {
jlong nanos_remaining = nanos;
for (;;) {
if (has_async_exception_condition()) {
return false;
}
// interruption has precedence over timing out
if (this->is_interrupted(true)) {
return false;

View File

@ -211,7 +211,6 @@ public class StopThreadTest {
log("TestTask.run: caught expected AssertionError from method A()");
seenExceptionFromA = true;
}
Thread.interrupted();
if (!seenExceptionFromA && !preemptableVirtualThread()) {
StopThreadTest.setFailed("TestTask.run: expected AssertionError from method A()");
}
@ -224,7 +223,6 @@ public class StopThreadTest {
log("TestTask.run: caught expected AssertionError from method B()");
seenExceptionFromB = true;
}
Thread.interrupted();
if (!seenExceptionFromB) {
StopThreadTest.setFailed("TestTask.run: expected AssertionError from method B()");
}
@ -237,7 +235,6 @@ public class StopThreadTest {
log("TestTask.run: caught expected AssertionError from method C()");
seenExceptionFromC = true;
}
Thread.interrupted();
if (!seenExceptionFromC) {
StopThreadTest.setFailed("TestTask.run: expected AssertionError from method C()");
}