< prev index next >

src/os/posix/vm/os_posix.cpp

Print this page
rev 8910 : full patch for jfr

@@ -1,7 +1,7 @@
 /*
-* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+* 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,10 +827,72 @@
   } 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 >