< prev index next >
src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
Print this page
@@ -330,37 +330,31 @@
}
}
/*
* We are just about to exit the VM, so we will be very aggressive
-* at this point in order to increase overall success of dumping jfr data:
-*
-* 1. if the thread state is not "_thread_in_vm", we will quick transition
-* it to "_thread_in_vm".
-* 2. if the thread is the owner of some critical lock(s), unlock them.
+* at this point in order to increase overall success of dumping jfr data.
*
* 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 (disallow WatcherThread to emergency dump).
* This "safety net" somewhat explains the aggressiveness in this attempt.
*
*/
static bool prepare_for_emergency_dump() {
+ Thread* const thread = Thread::current_or_null_safe();
+ assert(thread != NULL, "invariant");
+
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);
- }
-
#ifdef ASSERT
Mutex* owned_lock = thread->owned_locks();
while (owned_lock != NULL) {
Mutex* next = owned_lock->next();
owned_lock->unlock();
@@ -426,14 +420,47 @@
static bool guard_reentrancy() {
return Atomic::cmpxchg(1, &jfr_shutdown_lock, 0) == 0;
}
+class JavaThreadInVM : public StackObj {
+ private:
+ JavaThread* _jt;
+ JavaThreadState _original_state;
+
+ public:
+
+ JavaThreadInVM(Thread* thread) : _jt(NULL),
+ _original_state(_thread_max_state) {
+ if ((thread != NULL) && thread->is_Java_thread()) {
+ _jt = (JavaThread*)thread;
+ _original_state = _jt->thread_state();
+ _jt->set_thread_state(_thread_in_vm);
+ }
+ }
+
+ ~JavaThreadInVM() {
+ if (_jt != NULL) {
+ _jt->set_thread_state(_original_state);
+ }
+ }
+
+};
+
void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) {
- if (!(guard_reentrancy() && prepare_for_emergency_dump())) {
+ if (!guard_reentrancy()) {
return;
}
+
+ Thread* thread = Thread::current_or_null_safe();
+
+ // Ensure a JavaThread is _thread_in_vm when we make this call
+ JavaThreadInVM jtivm(thread);
+ if ((thread != NULL) && !prepare_for_emergency_dump()) {
+ return;
+ }
+
EventDumpReason event;
if (event.should_commit()) {
event.set_reason(exception_handler ? "Crash" : "Out of Memory");
event.set_recordingId(-1);
event.commit();
< prev index next >