< prev index next >
src/os/posix/vm/os_posix.cpp
Print this page
rev 13203 : [mq]: 8183925
*** 1282,1343 ****
}
return stack_size;
}
! 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();
}
}
}
#define check_with_errno(check_type, cond, msg) \
--- 1282,1349 ----
}
return stack_size;
}
! Thread* os::ThreadCrashProtection::_protected_thread = NULL;
! os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL;
! volatile intptr_t os::ThreadCrashProtection::_crash_mux = 0;
!
! os::ThreadCrashProtection::ThreadCrashProtection() {
}
/*
* 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::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
sigset_t saved_sig_mask;
! Thread::muxAcquire(&_crash_mux, "CrashProtection");
!
! _protected_thread = Thread::current_or_null();
! assert(_protected_thread != NULL, "Cannot crash protect a none Thread");
// 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
! _crash_protection = this;
cb.call();
// and clear the crash protection
! _crash_protection = NULL;
! _protected_thread = NULL;
! Thread::muxRelease(&_crash_mux);
return true;
}
// this happens when we siglongjmp() back
pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
! _crash_protection = NULL;
! _protected_thread = NULL;
! Thread::muxRelease(&_crash_mux);
return false;
}
! void os::ThreadCrashProtection::restore() {
! assert(_crash_protection != NULL, "must have crash protection");
siglongjmp(_jmpbuf, 1);
}
! void os::ThreadCrashProtection::check_crash_protection(int sig,
Thread* thread) {
if (thread != NULL &&
! thread == _protected_thread &&
! _crash_protection != NULL) {
if (sig == SIGSEGV || sig == SIGBUS) {
! _crash_protection->restore();
}
}
}
#define check_with_errno(check_type, cond, msg) \
< prev index next >