提交 9dd0bdd6 编写于 作者: R rehn

8183925: Decouple crash protection from watcher thread

Reviewed-by: dcubed, coleenp
上级 7b38ecef
...@@ -919,59 +919,3 @@ void os::ThreadCrashProtection::check_crash_protection(int sig, ...@@ -919,59 +919,3 @@ void os::ThreadCrashProtection::check_crash_protection(int sig,
} }
} }
} }
os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
}
/*
* See the caveats for this class in os_posix.hpp
* Protects the callback call so that SIGSEGV / SIGBUS jumps back into this
* method and returns false. If none of the signals are raised, returns true.
* The callback is supposed to provide the method that should be protected.
*/
bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
sigset_t saved_sig_mask;
assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread");
assert(!WatcherThread::watcher_thread()->has_crash_protection(),
"crash_protection already set?");
// we cannot rely on sigsetjmp/siglongjmp to save/restore the signal mask
// since on at least some systems (OS X) siglongjmp will restore the mask
// for the process, not the thread
pthread_sigmask(0, NULL, &saved_sig_mask);
if (sigsetjmp(_jmpbuf, 0) == 0) {
// make sure we can see in the signal handler that we have crash protection
// installed
WatcherThread::watcher_thread()->set_crash_protection(this);
cb.call();
// and clear the crash protection
WatcherThread::watcher_thread()->set_crash_protection(NULL);
return true;
}
// this happens when we siglongjmp() back
pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
WatcherThread::watcher_thread()->set_crash_protection(NULL);
return false;
}
void os::WatcherThreadCrashProtection::restore() {
assert(WatcherThread::watcher_thread()->has_crash_protection(),
"must have crash protection");
siglongjmp(_jmpbuf, 1);
}
void os::WatcherThreadCrashProtection::check_crash_protection(int sig,
Thread* thread) {
if (thread != NULL &&
thread->is_Watcher_thread() &&
WatcherThread::watcher_thread()->has_crash_protection()) {
if (sig == SIGSEGV || sig == SIGBUS) {
WatcherThread::watcher_thread()->crash_protection()->restore();
}
}
}
...@@ -88,24 +88,4 @@ private: ...@@ -88,24 +88,4 @@ private:
sigjmp_buf _jmpbuf; sigjmp_buf _jmpbuf;
}; };
/*
* Crash protection for the watcher thread. Wrap the callback
* with a sigsetjmp and in case of a SIGSEGV/SIGBUS we siglongjmp
* back.
* To be able to use this - don't take locks, don't rely on destructors,
* don't make OS library calls, don't allocate memory, don't print,
* don't call code that could leave the heap / memory in an inconsistent state,
* or anything else where we are not in control if we suddenly jump out.
*/
class WatcherThreadCrashProtection : public StackObj {
public:
WatcherThreadCrashProtection();
bool call(os::CrashProtectionCallback& cb);
static void check_crash_protection(int signal, Thread* thread);
private:
void restore();
sigjmp_buf _jmpbuf;
};
#endif // OS_POSIX_VM_OS_POSIX_HPP #endif // OS_POSIX_VM_OS_POSIX_HPP
...@@ -4905,34 +4905,6 @@ bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) { ...@@ -4905,34 +4905,6 @@ bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
return success; return success;
} }
os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
}
/*
* See the caveats for this class in os_windows.hpp
* Protects the callback call so that raised OS EXCEPTIONS causes a jump back
* into this method and returns false. If no OS EXCEPTION was raised, returns
* true.
* The callback is supposed to provide the method that should be protected.
*/
bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread");
assert(!WatcherThread::watcher_thread()->has_crash_protection(),
"crash_protection already set?");
bool success = true;
__try {
WatcherThread::watcher_thread()->set_crash_protection(this);
cb.call();
} __except(EXCEPTION_EXECUTE_HANDLER) {
// only for protection, nothing to do
success = false;
}
WatcherThread::watcher_thread()->set_crash_protection(NULL);
return success;
}
// An Event wraps a win32 "CreateEvent" kernel handle. // An Event wraps a win32 "CreateEvent" kernel handle.
// //
// We have a number of choices regarding "CreateEvent" win32 handle leakage: // We have a number of choices regarding "CreateEvent" win32 handle leakage:
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -125,20 +125,6 @@ private: ...@@ -125,20 +125,6 @@ private:
static volatile intptr_t _crash_mux; static volatile intptr_t _crash_mux;
}; };
/*
* Crash protection for the watcher thread. Wrap the callback
* with a __try { call() }
* To be able to use this - don't take locks, don't rely on destructors,
* don't make OS library calls, don't allocate memory, don't print,
* don't call code that could leave the heap / memory in an inconsistent state,
* or anything else where we are not in control if we suddenly jump out.
*/
class WatcherThreadCrashProtection : public StackObj {
public:
WatcherThreadCrashProtection();
bool call(os::CrashProtectionCallback& cb);
};
class PlatformEvent : public CHeapObj<mtInternal> { class PlatformEvent : public CHeapObj<mtInternal> {
private: private:
double CachePad [4] ; // increase odds that _Event is sole occupant of cache line double CachePad [4] ; // increase odds that _Event is sole occupant of cache line
......
...@@ -407,7 +407,7 @@ JVM_handle_bsd_signal(int sig, ...@@ -407,7 +407,7 @@ JVM_handle_bsd_signal(int sig,
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run) // (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t); os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t); SignalHandlerMark shm(t);
......
...@@ -544,7 +544,7 @@ JVM_handle_linux_signal(int sig, ...@@ -544,7 +544,7 @@ JVM_handle_linux_signal(int sig,
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run) // (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t); os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t); SignalHandlerMark shm(t);
......
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -222,7 +222,7 @@ JVM_handle_linux_signal(int sig, ...@@ -222,7 +222,7 @@ JVM_handle_linux_signal(int sig,
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run) // (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t); os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t); SignalHandlerMark shm(t);
......
...@@ -312,7 +312,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, ...@@ -312,7 +312,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run) // (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t); os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t); SignalHandlerMark shm(t);
......
...@@ -369,7 +369,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, ...@@ -369,7 +369,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run) // (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t); os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t); SignalHandlerMark shm(t);
......
/* /*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1373,10 +1373,8 @@ void Monitor::check_prelock_state(Thread *thread) { ...@@ -1373,10 +1373,8 @@ void Monitor::check_prelock_state(Thread *thread) {
debug_only(if (rank() != Mutex::special) \ debug_only(if (rank() != Mutex::special) \
thread->check_for_valid_safepoint_state(false);) thread->check_for_valid_safepoint_state(false);)
} }
if (thread->is_Watcher_thread()) { assert(!os::ThreadCrashProtection::is_crash_protected(thread),
assert(!WatcherThread::watcher_thread()->has_crash_protection(), "locking not allowed when crash protection is set");
"locking not allowed when crash protection is set");
}
} }
void Monitor::check_block_state(Thread *thread) { void Monitor::check_block_state(Thread *thread) {
......
...@@ -593,21 +593,10 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { ...@@ -593,21 +593,10 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
#ifdef ASSERT // Since os::malloc can be called when the libjvm.{dll,so} is
// checking for the WatcherThread and crash_protection first // first loaded and we don't have a thread yet we must accept NULL also here.
// since os::malloc can be called when the libjvm.{dll,so} is assert(!os::ThreadCrashProtection::is_crash_protected(ThreadLocalStorage::thread()),
// first loaded and we don't have a thread yet. "malloc() not allowed when crash protection is set");
// try to find the thread after we see that the watcher thread
// exists and has crash protection.
WatcherThread *wt = WatcherThread::watcher_thread();
if (wt != NULL && wt->has_crash_protection()) {
Thread* thread = ThreadLocalStorage::get_thread_slow();
if (thread == wt) {
assert(!wt->has_crash_protection(),
"Can't malloc with crash protection from WatcherThread");
}
}
#endif
if (size == 0) { if (size == 0) {
// return a valid pointer if size is zero // return a valid pointer if size is zero
......
...@@ -1239,7 +1239,7 @@ WatcherThread* WatcherThread::_watcher_thread = NULL; ...@@ -1239,7 +1239,7 @@ WatcherThread* WatcherThread::_watcher_thread = NULL;
bool WatcherThread::_startable = false; bool WatcherThread::_startable = false;
volatile bool WatcherThread::_should_terminate = false; volatile bool WatcherThread::_should_terminate = false;
WatcherThread::WatcherThread() : Thread(), _crash_protection(NULL) { WatcherThread::WatcherThread() : Thread() {
assert(watcher_thread() == NULL, "we can only allocate one WatcherThread"); assert(watcher_thread() == NULL, "we can only allocate one WatcherThread");
if (os::create_thread(this, os::watcher_thread)) { if (os::create_thread(this, os::watcher_thread)) {
_watcher_thread = this; _watcher_thread = this;
......
...@@ -734,8 +734,6 @@ class WatcherThread: public Thread { ...@@ -734,8 +734,6 @@ class WatcherThread: public Thread {
static bool _startable; static bool _startable;
volatile static bool _should_terminate; // updated without holding lock volatile static bool _should_terminate; // updated without holding lock
os::WatcherThreadCrashProtection* _crash_protection;
public: public:
enum SomeConstants { enum SomeConstants {
delay_interval = 10 // interrupt delay in milliseconds delay_interval = 10 // interrupt delay in milliseconds
...@@ -762,15 +760,6 @@ class WatcherThread: public Thread { ...@@ -762,15 +760,6 @@ class WatcherThread: public Thread {
// Only allow start once the VM is sufficiently initialized // Only allow start once the VM is sufficiently initialized
// Otherwise the first task to enroll will trigger the start // Otherwise the first task to enroll will trigger the start
static void make_startable(); static void make_startable();
void set_crash_protection(os::WatcherThreadCrashProtection* crash_protection) {
assert(Thread::current()->is_Watcher_thread(), "Can only be set by WatcherThread");
_crash_protection = crash_protection;
}
bool has_crash_protection() const { return _crash_protection != NULL; }
os::WatcherThreadCrashProtection* crash_protection() const { return _crash_protection; }
private: private:
int sleep() const; int sleep() const;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册