< prev index next >

src/os/posix/vm/os_posix.cpp

Print this page
rev 8910 : full patch for jfr

*** 1,7 **** /* ! * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 827,836 **** --- 827,898 ---- } else if (sig == SIGCHLD) { os->print_cr(", si_pid: %d, si_uid: %d, si_status: %d", (int) si->si_pid, si->si_uid, si->si_status); } } + 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 = ThreadLocalStorage::thread(); + assert(_protected_thread != NULL, "Cannot crash protect a NULL 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(); + } + } + } + os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); } /*
< prev index next >