src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
branchJEP-349-branch
changeset 58823 6a21dba79b81
parent 58578 7b89c53db169
equal deleted inserted replaced
58806:a7d850b47b19 58823:6a21dba79b81
   334 * We are just about to exit the VM, so we will be very aggressive
   334 * We are just about to exit the VM, so we will be very aggressive
   335 * at this point in order to increase overall success of dumping jfr data:
   335 * at this point in order to increase overall success of dumping jfr data:
   336 *
   336 *
   337 * 1. if the thread state is not "_thread_in_vm", we will quick transition
   337 * 1. if the thread state is not "_thread_in_vm", we will quick transition
   338 *    it to "_thread_in_vm".
   338 *    it to "_thread_in_vm".
   339 * 2. the nesting state for both resource and handle areas are unknown,
   339 * 2. if the thread is the owner of some critical lock(s), unlock them.
   340 *    so we allocate new fresh arenas, discarding the old ones.
       
   341 * 3. if the thread is the owner of some critical lock(s), unlock them.
       
   342 *
   340 *
   343 * If we end up deadlocking in the attempt of dumping out jfr data,
   341 * If we end up deadlocking in the attempt of dumping out jfr data,
   344 * we rely on the WatcherThread task "is_error_reported()",
   342 * we rely on the WatcherThread task "is_error_reported()",
   345 * to exit the VM after a hard-coded timeout.
   343 * to exit the VM after a hard-coded timeout (disallow WatcherThread to emergency dump).
   346 * This "safety net" somewhat explains the aggressiveness in this attempt.
   344 * This "safety net" somewhat explains the aggressiveness in this attempt.
   347 *
   345 *
   348 */
   346 */
   349 static void prepare_for_emergency_dump(Thread* thread) {
   347 static bool prepare_for_emergency_dump() {
       
   348   if (JfrStream_lock->owned_by_self()) {
       
   349     // crashed during jfr rotation, disallow recursion
       
   350     return false;
       
   351   }
       
   352   Thread* const thread = Thread::current();
       
   353   if (thread->is_Watcher_thread()) {
       
   354     // need WatcherThread as a safeguard against potential deadlocks
       
   355     return false;
       
   356   }
       
   357 
   350   if (thread->is_Java_thread()) {
   358   if (thread->is_Java_thread()) {
   351     ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
   359     ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
   352   }
   360   }
   353 
   361 
   354 #ifdef ASSERT
   362 #ifdef ASSERT
   382 
   390 
   383   if (VMOperationRequest_lock->owned_by_self()) {
   391   if (VMOperationRequest_lock->owned_by_self()) {
   384     VMOperationRequest_lock->unlock();
   392     VMOperationRequest_lock->unlock();
   385   }
   393   }
   386 
   394 
   387 
       
   388   if (Service_lock->owned_by_self()) {
   395   if (Service_lock->owned_by_self()) {
   389     Service_lock->unlock();
   396     Service_lock->unlock();
   390   }
   397   }
   391 
   398 
   392   if (UseNotificationThread && Notification_lock->owned_by_self()) {
   399   if (UseNotificationThread && Notification_lock->owned_by_self()) {
   410   }
   417   }
   411 
   418 
   412   if (JfrStacktrace_lock->owned_by_self()) {
   419   if (JfrStacktrace_lock->owned_by_self()) {
   413     JfrStacktrace_lock->unlock();
   420     JfrStacktrace_lock->unlock();
   414   }
   421   }
       
   422   return true;
   415 }
   423 }
   416 
   424 
   417 static volatile int jfr_shutdown_lock = 0;
   425 static volatile int jfr_shutdown_lock = 0;
   418 
   426 
   419 static bool guard_reentrancy() {
   427 static bool guard_reentrancy() {
   420   return Atomic::cmpxchg(1, &jfr_shutdown_lock, 0) == 0;
   428   return Atomic::cmpxchg(1, &jfr_shutdown_lock, 0) == 0;
   421 }
   429 }
   422 
   430 
   423 void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) {
   431 void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) {
   424   if (!guard_reentrancy()) {
   432   if (!(guard_reentrancy() && prepare_for_emergency_dump())) {
   425     return;
   433     return;
   426   }
       
   427   // function made non-reentrant
       
   428   Thread* thread = Thread::current();
       
   429   if (exception_handler) {
       
   430     // we are crashing
       
   431     if (thread->is_Watcher_thread()) {
       
   432       // The Watcher thread runs the periodic thread sampling task.
       
   433       // If it has crashed, it is likely that another thread is
       
   434       // left in a suspended state. This would mean the system
       
   435       // will not be able to ever move to a safepoint. We try
       
   436       // to avoid issuing safepoint operations when attempting
       
   437       // an emergency dump, but a safepoint might be already pending.
       
   438       return;
       
   439     }
       
   440     prepare_for_emergency_dump(thread);
       
   441   }
   434   }
   442   EventDumpReason event;
   435   EventDumpReason event;
   443   if (event.should_commit()) {
   436   if (event.should_commit()) {
   444     event.set_reason(exception_handler ? "Crash" : "Out of Memory");
   437     event.set_reason(exception_handler ? "Crash" : "Out of Memory");
   445     event.set_recordingId(-1);
   438     event.set_recordingId(-1);
   448   if (!exception_handler) {
   441   if (!exception_handler) {
   449     // OOM
   442     // OOM
   450     LeakProfiler::emit_events(max_jlong, false);
   443     LeakProfiler::emit_events(max_jlong, false);
   451   }
   444   }
   452   const int messages = MSGBIT(MSG_VM_ERROR);
   445   const int messages = MSGBIT(MSG_VM_ERROR);
   453   ResourceMark rm(thread);
       
   454   HandleMark hm(thread);
       
   455   JfrRecorderService service;
   446   JfrRecorderService service;
   456   service.rotate(messages);
   447   service.rotate(messages);
   457 }
   448 }