src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
changeset 58863 c16ac7a2eba4
parent 58503 726a3945e934
child 58945 a3b046720c3b
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
   246     }
   246     }
   247   }
   247   }
   248 }
   248 }
   249 
   249 
   250 static const char* create_emergency_dump_path() {
   250 static const char* create_emergency_dump_path() {
   251   assert(JfrStream_lock->owned_by_self(), "invariant");
       
   252   char* buffer = NEW_RESOURCE_ARRAY_RETURN_NULL(char, JVM_MAXPATHLEN);
   251   char* buffer = NEW_RESOURCE_ARRAY_RETURN_NULL(char, JVM_MAXPATHLEN);
   253   if (NULL == buffer) {
   252   if (NULL == buffer) {
   254     return NULL;
   253     return NULL;
   255   }
   254   }
   256   const char* const cwd = os::get_current_directory(buffer, JVM_MAXPATHLEN);
   255   const char* const cwd = os::get_current_directory(buffer, JVM_MAXPATHLEN);
   289 }
   288 }
   290 
   289 
   291 // Caller needs ResourceMark
   290 // Caller needs ResourceMark
   292 static const char* create_emergency_chunk_path(const char* repository_path) {
   291 static const char* create_emergency_chunk_path(const char* repository_path) {
   293   assert(repository_path != NULL, "invariant");
   292   assert(repository_path != NULL, "invariant");
   294   assert(JfrStream_lock->owned_by_self(), "invariant");
       
   295   const size_t repository_path_len = strlen(repository_path);
   293   const size_t repository_path_len = strlen(repository_path);
   296   // date time
   294   // date time
   297   char date_time_buffer[32] = { 0 };
   295   char date_time_buffer[32] = { 0 };
   298   date_time(date_time_buffer, sizeof(date_time_buffer));
   296   date_time(date_time_buffer, sizeof(date_time_buffer));
   299   size_t date_time_len = strlen(date_time_buffer);
   297   size_t date_time_len = strlen(date_time_buffer);
   305   char* chunk_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, chunkname_max_len);
   303   char* chunk_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, chunkname_max_len);
   306   if (chunk_path == NULL) {
   304   if (chunk_path == NULL) {
   307     return NULL;
   305     return NULL;
   308   }
   306   }
   309   // append the individual substrings
   307   // append the individual substrings
   310   jio_snprintf(chunk_path, chunkname_max_len, "%s%s%s%s", repository_path_len, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
   308   jio_snprintf(chunk_path, chunkname_max_len, "%s%s%s%s", repository_path, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
   311   return chunk_path;
   309   return chunk_path;
   312 }
   310 }
   313 
   311 
   314 static fio_fd emergency_dump_file_descriptor() {
   312 static fio_fd emergency_dump_file_descriptor() {
   315   assert(JfrStream_lock->owned_by_self(), "invariant");
       
   316   ResourceMark rm;
   313   ResourceMark rm;
   317   const char* const emergency_dump_path = create_emergency_dump_path();
   314   const char* const emergency_dump_path = create_emergency_dump_path();
   318   return emergency_dump_path != NULL ? open_exclusivly(emergency_dump_path) : invalid_fd;
   315   return emergency_dump_path != NULL ? open_exclusivly(emergency_dump_path) : invalid_fd;
   319 }
   316 }
   320 
   317 
   323 }
   320 }
   324 
   321 
   325 void JfrEmergencyDump::on_vm_error(const char* repository_path) {
   322 void JfrEmergencyDump::on_vm_error(const char* repository_path) {
   326   assert(repository_path != NULL, "invariant");
   323   assert(repository_path != NULL, "invariant");
   327   ResourceMark rm;
   324   ResourceMark rm;
   328   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
       
   329   const fio_fd emergency_fd = emergency_dump_file_descriptor();
   325   const fio_fd emergency_fd = emergency_dump_file_descriptor();
   330   if (emergency_fd != invalid_fd) {
   326   if (emergency_fd != invalid_fd) {
   331     RepositoryIterator iterator(repository_path, strlen(repository_path));
   327     RepositoryIterator iterator(repository_path, strlen(repository_path));
   332     write_emergency_file(emergency_fd, iterator);
   328     write_emergency_file(emergency_fd, iterator);
   333     os::close(emergency_fd);
   329     os::close(emergency_fd);
   338 * 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
   339 * 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:
   340 *
   336 *
   341 * 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
   342 *    it to "_thread_in_vm".
   338 *    it to "_thread_in_vm".
   343 * 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.
   344 *    so we allocate new fresh arenas, discarding the old ones.
       
   345 * 3. if the thread is the owner of some critical lock(s), unlock them.
       
   346 *
   340 *
   347 * 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,
   348 * we rely on the WatcherThread task "is_error_reported()",
   342 * we rely on the WatcherThread task "is_error_reported()",
   349 * to exit the VM after a hard-coded timeout.
   343 * to exit the VM after a hard-coded timeout (disallow WatcherThread to emergency dump).
   350 * This "safety net" somewhat explains the aggressiveness in this attempt.
   344 * This "safety net" somewhat explains the aggressiveness in this attempt.
   351 *
   345 *
   352 */
   346 */
   353 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 
   354   if (thread->is_Java_thread()) {
   358   if (thread->is_Java_thread()) {
   355     ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
   359     ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
   356   }
   360   }
   357 
   361 
   358 #ifdef ASSERT
   362 #ifdef ASSERT
   386 
   390 
   387   if (VMOperationRequest_lock->owned_by_self()) {
   391   if (VMOperationRequest_lock->owned_by_self()) {
   388     VMOperationRequest_lock->unlock();
   392     VMOperationRequest_lock->unlock();
   389   }
   393   }
   390 
   394 
   391 
       
   392   if (Service_lock->owned_by_self()) {
   395   if (Service_lock->owned_by_self()) {
   393     Service_lock->unlock();
   396     Service_lock->unlock();
   394   }
   397   }
   395 
   398 
   396   if (UseNotificationThread && Notification_lock->owned_by_self()) {
   399   if (UseNotificationThread && Notification_lock->owned_by_self()) {
   411 
   414 
   412   if (JfrBuffer_lock->owned_by_self()) {
   415   if (JfrBuffer_lock->owned_by_self()) {
   413     JfrBuffer_lock->unlock();
   416     JfrBuffer_lock->unlock();
   414   }
   417   }
   415 
   418 
   416   if (JfrStream_lock->owned_by_self()) {
       
   417     JfrStream_lock->unlock();
       
   418   }
       
   419 
       
   420   if (JfrStacktrace_lock->owned_by_self()) {
   419   if (JfrStacktrace_lock->owned_by_self()) {
   421     JfrStacktrace_lock->unlock();
   420     JfrStacktrace_lock->unlock();
   422   }
   421   }
       
   422   return true;
   423 }
   423 }
   424 
   424 
   425 static volatile int jfr_shutdown_lock = 0;
   425 static volatile int jfr_shutdown_lock = 0;
   426 
   426 
   427 static bool guard_reentrancy() {
   427 static bool guard_reentrancy() {
   428   return Atomic::cmpxchg(1, &jfr_shutdown_lock, 0) == 0;
   428   return Atomic::cmpxchg(1, &jfr_shutdown_lock, 0) == 0;
   429 }
   429 }
   430 
   430 
   431 void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) {
   431 void JfrEmergencyDump::on_vm_shutdown(bool exception_handler) {
   432   if (!guard_reentrancy()) {
   432   if (!(guard_reentrancy() && prepare_for_emergency_dump())) {
   433     return;
   433     return;
   434   }
       
   435   // function made non-reentrant
       
   436   Thread* thread = Thread::current();
       
   437   if (exception_handler) {
       
   438     // we are crashing
       
   439     if (thread->is_Watcher_thread()) {
       
   440       // The Watcher thread runs the periodic thread sampling task.
       
   441       // If it has crashed, it is likely that another thread is
       
   442       // left in a suspended state. This would mean the system
       
   443       // will not be able to ever move to a safepoint. We try
       
   444       // to avoid issuing safepoint operations when attempting
       
   445       // an emergency dump, but a safepoint might be already pending.
       
   446       return;
       
   447     }
       
   448     prepare_for_emergency_dump(thread);
       
   449   }
   434   }
   450   EventDumpReason event;
   435   EventDumpReason event;
   451   if (event.should_commit()) {
   436   if (event.should_commit()) {
   452     event.set_reason(exception_handler ? "Crash" : "Out of Memory");
   437     event.set_reason(exception_handler ? "Crash" : "Out of Memory");
   453     event.set_recordingId(-1);
   438     event.set_recordingId(-1);
   456   if (!exception_handler) {
   441   if (!exception_handler) {
   457     // OOM
   442     // OOM
   458     LeakProfiler::emit_events(max_jlong, false);
   443     LeakProfiler::emit_events(max_jlong, false);
   459   }
   444   }
   460   const int messages = MSGBIT(MSG_VM_ERROR);
   445   const int messages = MSGBIT(MSG_VM_ERROR);
   461   ResourceMark rm(thread);
       
   462   HandleMark hm(thread);
       
   463   JfrRecorderService service;
   446   JfrRecorderService service;
   464   service.rotate(messages);
   447   service.rotate(messages);
   465 }
   448 }