src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
branchJEP-349-branch
changeset 58823 6a21dba79b81
parent 58578 7b89c53db169
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Sat Oct 26 23:59:51 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Mon Oct 28 18:43:04 2019 +0100
@@ -336,17 +336,25 @@
 *
 * 1. if the thread state is not "_thread_in_vm", we will quick transition
 *    it to "_thread_in_vm".
-* 2. the nesting state for both resource and handle areas are unknown,
-*    so we allocate new fresh arenas, discarding the old ones.
-* 3. if the thread is the owner of some critical lock(s), unlock them.
+* 2. if the thread is the owner of some critical lock(s), unlock them.
 *
 * If we end up deadlocking in the attempt of dumping out jfr data,
 * we rely on the WatcherThread task "is_error_reported()",
-* to exit the VM after a hard-coded timeout.
+* to exit the VM after a hard-coded timeout (disallow WatcherThread to emergency dump).
 * This "safety net" somewhat explains the aggressiveness in this attempt.
 *
 */
-static void prepare_for_emergency_dump(Thread* thread) {
+static bool prepare_for_emergency_dump() {
+  if (JfrStream_lock->owned_by_self()) {
+    // crashed during jfr rotation, disallow recursion
+    return false;
+  }
+  Thread* const thread = Thread::current();
+  if (thread->is_Watcher_thread()) {
+    // need WatcherThread as a safeguard against potential deadlocks
+    return false;
+  }
+
   if (thread->is_Java_thread()) {
     ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
   }
@@ -384,7 +392,6 @@
     VMOperationRequest_lock->unlock();
   }
 
-
   if (Service_lock->owned_by_self()) {
     Service_lock->unlock();
   }
@@ -412,6 +419,7 @@
   if (JfrStacktrace_lock->owned_by_self()) {
     JfrStacktrace_lock->unlock();
   }
+  return true;
 }
 
 static volatile int jfr_shutdown_lock = 0;
@@ -421,24 +429,9 @@
 }
 
 void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) {
-  if (!guard_reentrancy()) {
+  if (!(guard_reentrancy() && prepare_for_emergency_dump())) {
     return;
   }
-  // function made non-reentrant
-  Thread* thread = Thread::current();
-  if (exception_handler) {
-    // we are crashing
-    if (thread->is_Watcher_thread()) {
-      // The Watcher thread runs the periodic thread sampling task.
-      // If it has crashed, it is likely that another thread is
-      // left in a suspended state. This would mean the system
-      // will not be able to ever move to a safepoint. We try
-      // to avoid issuing safepoint operations when attempting
-      // an emergency dump, but a safepoint might be already pending.
-      return;
-    }
-    prepare_for_emergency_dump(thread);
-  }
   EventDumpReason event;
   if (event.should_commit()) {
     event.set_reason(exception_handler ? "Crash" : "Out of Memory");
@@ -450,8 +443,6 @@
     LeakProfiler::emit_events(max_jlong, false);
   }
   const int messages = MSGBIT(MSG_VM_ERROR);
-  ResourceMark rm(thread);
-  HandleMark hm(thread);
   JfrRecorderService service;
   service.rotate(messages);
 }