8282952: Thread::exit should be immune to Thread.stop
Reviewed-by: dcubed, pchilanomate, alanb
This commit is contained in:
parent
33eb89dfeb
commit
8cc1235029
@ -1373,12 +1373,13 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call Thread.exit(). We try 3 times in case we got another Thread.stop during
|
|
||||||
// the execution of the method. If that is not enough, then we don't really care. Thread.stop
|
|
||||||
// is deprecated anyhow.
|
|
||||||
if (!is_Compiler_thread()) {
|
if (!is_Compiler_thread()) {
|
||||||
int count = 3;
|
// We have finished executing user-defined Java code and now have to do the
|
||||||
while (java_lang_Thread::threadGroup(threadObj()) != NULL && (count-- > 0)) {
|
// implementation specific clean-up by calling Thread.exit(). We prevent any
|
||||||
|
// asynchronous exceptions from being delivered while in Thread.exit()
|
||||||
|
// to ensure the clean-up is not corrupted.
|
||||||
|
NoAsyncExceptionDeliveryMark _no_async(this);
|
||||||
|
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
JavaValue result(T_VOID);
|
JavaValue result(T_VOID);
|
||||||
Klass* thread_klass = vmClasses::Thread_klass();
|
Klass* thread_klass = vmClasses::Thread_klass();
|
||||||
@ -1389,7 +1390,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
|
|||||||
THREAD);
|
THREAD);
|
||||||
CLEAR_PENDING_EXCEPTION;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// notify JVMTI
|
// notify JVMTI
|
||||||
if (JvmtiExport::should_post_thread_life()) {
|
if (JvmtiExport::should_post_thread_life()) {
|
||||||
JvmtiExport::post_thread_end(this);
|
JvmtiExport::post_thread_end(this);
|
||||||
@ -1592,7 +1593,7 @@ void JavaThread::check_and_handle_async_exceptions() {
|
|||||||
// If we are at a polling page safepoint (not a poll return)
|
// If we are at a polling page safepoint (not a poll return)
|
||||||
// then we must defer async exception because live registers
|
// then we must defer async exception because live registers
|
||||||
// will be clobbered by the exception path. Poll return is
|
// will be clobbered by the exception path. Poll return is
|
||||||
// ok because the call we a returning from already collides
|
// ok because the call we are returning from already collides
|
||||||
// with exception handling registers and so there is no issue.
|
// with exception handling registers and so there is no issue.
|
||||||
// (The exception handling path kills call result registers but
|
// (The exception handling path kills call result registers but
|
||||||
// this is ok since the exception kills the result anyway).
|
// this is ok since the exception kills the result anyway).
|
||||||
@ -1613,6 +1614,9 @@ void JavaThread::check_and_handle_async_exceptions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!clear_async_exception_condition()) {
|
if (!clear_async_exception_condition()) {
|
||||||
|
if ((_suspend_flags & _async_delivery_disabled) != 0) {
|
||||||
|
log_info(exceptions)("Async exception delivery is disabled");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,6 +786,7 @@ class JavaThread: public Thread {
|
|||||||
// NOTE: avoid using the sign-bit as cc generates different test code
|
// NOTE: avoid using the sign-bit as cc generates different test code
|
||||||
// when the sign-bit is used, and sometimes incorrectly - see CR 6398077
|
// when the sign-bit is used, and sometimes incorrectly - see CR 6398077
|
||||||
_has_async_exception = 0x00000001U, // there is a pending async exception
|
_has_async_exception = 0x00000001U, // there is a pending async exception
|
||||||
|
_async_delivery_disabled = 0x00000002U, // async exception delivery is disabled
|
||||||
_trace_flag = 0x00000004U, // call tracing backend
|
_trace_flag = 0x00000004U, // call tracing backend
|
||||||
_obj_deopt = 0x00000008U // suspend for object reallocation and relocking for JVMTI agent
|
_obj_deopt = 0x00000008U // suspend for object reallocation and relocking for JVMTI agent
|
||||||
};
|
};
|
||||||
@ -815,7 +816,8 @@ class JavaThread: public Thread {
|
|||||||
inline bool clear_async_exception_condition();
|
inline bool clear_async_exception_condition();
|
||||||
public:
|
public:
|
||||||
bool has_async_exception_condition() {
|
bool has_async_exception_condition() {
|
||||||
return (_suspend_flags & _has_async_exception) != 0;
|
return (_suspend_flags & _has_async_exception) != 0 &&
|
||||||
|
(_suspend_flags & _async_delivery_disabled) == 0;
|
||||||
}
|
}
|
||||||
inline void set_pending_async_exception(oop e);
|
inline void set_pending_async_exception(oop e);
|
||||||
inline void set_pending_unsafe_access_error();
|
inline void set_pending_unsafe_access_error();
|
||||||
@ -823,6 +825,13 @@ class JavaThread: public Thread {
|
|||||||
void send_thread_stop(oop throwable);
|
void send_thread_stop(oop throwable);
|
||||||
void check_and_handle_async_exceptions();
|
void check_and_handle_async_exceptions();
|
||||||
|
|
||||||
|
class NoAsyncExceptionDeliveryMark : public StackObj {
|
||||||
|
friend JavaThread;
|
||||||
|
JavaThread *_target;
|
||||||
|
inline NoAsyncExceptionDeliveryMark(JavaThread *t);
|
||||||
|
inline ~NoAsyncExceptionDeliveryMark();
|
||||||
|
};
|
||||||
|
|
||||||
// Safepoint support
|
// Safepoint support
|
||||||
public: // Expose _thread_state for SafeFetchInt()
|
public: // Expose _thread_state for SafeFetchInt()
|
||||||
volatile JavaThreadState _thread_state;
|
volatile JavaThreadState _thread_state;
|
||||||
|
@ -124,7 +124,9 @@ inline void JavaThread::clear_obj_deopt_flag() {
|
|||||||
|
|
||||||
inline bool JavaThread::clear_async_exception_condition() {
|
inline bool JavaThread::clear_async_exception_condition() {
|
||||||
bool ret = has_async_exception_condition();
|
bool ret = has_async_exception_condition();
|
||||||
|
if (ret) {
|
||||||
clear_suspend_flag(_has_async_exception);
|
clear_suspend_flag(_has_async_exception);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +140,15 @@ inline void JavaThread::set_pending_unsafe_access_error() {
|
|||||||
DEBUG_ONLY(_is_unsafe_access_error = true);
|
DEBUG_ONLY(_is_unsafe_access_error = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline JavaThread::NoAsyncExceptionDeliveryMark::NoAsyncExceptionDeliveryMark(JavaThread *t) : _target(t) {
|
||||||
|
assert((_target->_suspend_flags & _async_delivery_disabled) == 0, "Nesting is not supported");
|
||||||
|
_target->set_suspend_flag(_async_delivery_disabled);
|
||||||
|
}
|
||||||
|
inline JavaThread::NoAsyncExceptionDeliveryMark::~NoAsyncExceptionDeliveryMark() {
|
||||||
|
_target->clear_suspend_flag(_async_delivery_disabled);
|
||||||
|
}
|
||||||
|
|
||||||
inline JavaThreadState JavaThread::thread_state() const {
|
inline JavaThreadState JavaThread::thread_state() const {
|
||||||
#if defined(PPC64) || defined (AARCH64)
|
#if defined(PPC64) || defined (AARCH64)
|
||||||
// Use membars when accessing volatile _thread_state. See
|
// Use membars when accessing volatile _thread_state. See
|
||||||
|
Loading…
x
Reference in New Issue
Block a user