8159461: bigapps/Kitchensink/stressExitCode hits assert: Must be VMThread or JavaThread
Reviewed-by: fparain, simonis, dcubed
--- a/hotspot/src/os/aix/vm/os_aix.cpp Thu Aug 11 16:22:08 2016 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp Fri Aug 12 00:19:44 2016 -0400
@@ -2686,7 +2686,8 @@
// - sets target osthread state to continue
// - sends signal to end the sigsuspend loop in the SR_handler
//
-// Note that the SR_lock plays no role in this suspend/resume protocol.
+// Note that the SR_lock plays no role in this suspend/resume protocol,
+// but is checked for NULL in SR_handler as a thread termination indicator.
//
static void resume_clear_context(OSThread *osthread) {
@@ -2718,9 +2719,22 @@
// after sigsuspend.
int old_errno = errno;
- Thread* thread = Thread::current();
+ Thread* thread = Thread::current_or_null_safe();
+ assert(thread != NULL, "Missing current thread in SR_handler");
+
+ // On some systems we have seen signal delivery get "stuck" until the signal
+ // mask is changed as part of thread termination. Check that the current thread
+ // has not already terminated (via SR_lock()) - else the following assertion
+ // will fail because the thread is no longer a JavaThread as the ~JavaThread
+ // destructor has completed.
+
+ if (thread->SR_lock() == NULL) {
+ return;
+ }
+
+ assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
+
OSThread* osthread = thread->osthread();
- assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
os::SuspendResume::State current = osthread->sr.state();
if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Aug 11 16:22:08 2016 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Aug 12 00:19:44 2016 -0400
@@ -2716,7 +2716,8 @@
// - sets target osthread state to continue
// - sends signal to end the sigsuspend loop in the SR_handler
//
-// Note that the SR_lock plays no role in this suspend/resume protocol.
+// Note that the SR_lock plays no role in this suspend/resume protocol,
+// but is checked for NULL in SR_handler as a thread termination indicator.
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
@@ -2746,9 +2747,22 @@
// after sigsuspend.
int old_errno = errno;
- Thread* thread = Thread::current();
+ Thread* thread = Thread::current_or_null_safe();
+ assert(thread != NULL, "Missing current thread in SR_handler");
+
+ // On some systems we have seen signal delivery get "stuck" until the signal
+ // mask is changed as part of thread termination. Check that the current thread
+ // has not already terminated (via SR_lock()) - else the following assertion
+ // will fail because the thread is no longer a JavaThread as the ~JavaThread
+ // destructor has completed.
+
+ if (thread->SR_lock() == NULL) {
+ return;
+ }
+
+ assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
+
OSThread* osthread = thread->osthread();
- assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
os::SuspendResume::State current = osthread->sr.state();
if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Aug 11 16:22:08 2016 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Aug 12 00:19:44 2016 -0400
@@ -3971,7 +3971,8 @@
// - sets target osthread state to continue
// - sends signal to end the sigsuspend loop in the SR_handler
//
-// Note that the SR_lock plays no role in this suspend/resume protocol.
+// Note that the SR_lock plays no role in this suspend/resume protocol,
+// but is checked for NULL in SR_handler as a thread termination indicator.
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
@@ -4004,8 +4005,20 @@
Thread* thread = Thread::current_or_null_safe();
assert(thread != NULL, "Missing current thread in SR_handler");
+
+ // On some systems we have seen signal delivery get "stuck" until the signal
+ // mask is changed as part of thread termination. Check that the current thread
+ // has not already terminated (via SR_lock()) - else the following assertion
+ // will fail because the thread is no longer a JavaThread as the ~JavaThread
+ // destructor has completed.
+
+ if (thread->SR_lock() == NULL) {
+ return;
+ }
+
+ assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
+
OSThread* osthread = thread->osthread();
- assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
os::SuspendResume::State current = osthread->sr.state();
if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Aug 11 16:22:08 2016 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Aug 12 00:19:44 2016 -0400
@@ -374,11 +374,14 @@
delete handle_area();
delete metadata_handles();
+ // SR_handler uses this as a termination indicator -
+ // needs to happen before os::free_thread()
+ delete _SR_lock;
+ _SR_lock = NULL;
+
// osthread() can be NULL, if creation of thread failed.
if (osthread() != NULL) os::free_thread(osthread());
- delete _SR_lock;
-
// clear Thread::current if thread is deleting itself.
// Needed to ensure JNI correctly detects non-attached threads.
if (this == Thread::current()) {