330 } |
330 } |
331 } |
331 } |
332 |
332 |
333 /* |
333 /* |
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 * |
|
337 * 1. if the thread state is not "_thread_in_vm", we will quick transition |
|
338 * it to "_thread_in_vm". |
|
339 * 2. if the thread is the owner of some critical lock(s), unlock them. |
|
340 * |
336 * |
341 * If we end up deadlocking in the attempt of dumping out jfr data, |
337 * If we end up deadlocking in the attempt of dumping out jfr data, |
342 * we rely on the WatcherThread task "is_error_reported()", |
338 * we rely on the WatcherThread task "is_error_reported()", |
343 * to exit the VM after a hard-coded timeout (disallow WatcherThread to emergency dump). |
339 * to exit the VM after a hard-coded timeout (disallow WatcherThread to emergency dump). |
344 * This "safety net" somewhat explains the aggressiveness in this attempt. |
340 * This "safety net" somewhat explains the aggressiveness in this attempt. |
345 * |
341 * |
346 */ |
342 */ |
347 static bool prepare_for_emergency_dump() { |
343 static bool prepare_for_emergency_dump(Thread* thread) { |
|
344 assert(thread != NULL, "invariant"); |
|
345 |
|
346 if (thread->is_Watcher_thread()) { |
|
347 // need WatcherThread as a safeguard against potential deadlocks |
|
348 return false; |
|
349 } |
348 if (JfrStream_lock->owned_by_self()) { |
350 if (JfrStream_lock->owned_by_self()) { |
349 // crashed during jfr rotation, disallow recursion |
351 // crashed during jfr rotation, disallow recursion |
350 return false; |
352 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 |
|
358 if (thread->is_Java_thread()) { |
|
359 ((JavaThread*)thread)->set_thread_state(_thread_in_vm); |
|
360 } |
353 } |
361 |
354 |
362 #ifdef ASSERT |
355 #ifdef ASSERT |
363 Mutex* owned_lock = thread->owned_locks(); |
356 Mutex* owned_lock = thread->owned_locks(); |
364 while (owned_lock != NULL) { |
357 while (owned_lock != NULL) { |
426 |
419 |
427 static bool guard_reentrancy() { |
420 static bool guard_reentrancy() { |
428 return Atomic::cmpxchg(1, &jfr_shutdown_lock, 0) == 0; |
421 return Atomic::cmpxchg(1, &jfr_shutdown_lock, 0) == 0; |
429 } |
422 } |
430 |
423 |
|
424 class JavaThreadInVM : public StackObj { |
|
425 private: |
|
426 JavaThread* const _jt; |
|
427 JavaThreadState _original_state; |
|
428 public: |
|
429 |
|
430 JavaThreadInVM(Thread* t) : _jt(t->is_Java_thread() ? (JavaThread*)t : NULL), |
|
431 _original_state(_thread_max_state) { |
|
432 if ((_jt != NULL) && (_jt->thread_state() != _thread_in_vm)) { |
|
433 _original_state = _jt->thread_state(); |
|
434 _jt->set_thread_state(_thread_in_vm); |
|
435 } |
|
436 } |
|
437 |
|
438 ~JavaThreadInVM() { |
|
439 if (_original_state != _thread_max_state) { |
|
440 _jt->set_thread_state(_original_state); |
|
441 } |
|
442 } |
|
443 |
|
444 }; |
|
445 |
431 void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) { |
446 void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) { |
432 if (!(guard_reentrancy() && prepare_for_emergency_dump())) { |
447 if (!guard_reentrancy()) { |
433 return; |
448 return; |
434 } |
449 } |
|
450 |
|
451 Thread* thread = Thread::current_or_null_safe(); |
|
452 if (thread == NULL) { |
|
453 return; |
|
454 } |
|
455 // Ensure a JavaThread is _thread_in_vm when we make this call |
|
456 JavaThreadInVM jtivm(thread); |
|
457 if (!prepare_for_emergency_dump(thread)) { |
|
458 return; |
|
459 } |
|
460 |
435 EventDumpReason event; |
461 EventDumpReason event; |
436 if (event.should_commit()) { |
462 if (event.should_commit()) { |
437 event.set_reason(exception_handler ? "Crash" : "Out of Memory"); |
463 event.set_reason(exception_handler ? "Crash" : "Out of Memory"); |
438 event.set_recordingId(-1); |
464 event.set_recordingId(-1); |
439 event.commit(); |
465 event.commit(); |