< prev index next >

src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp

Print this page




  29 #include "jfr/recorder/repository/jfrEmergencyDump.hpp"
  30 #include "jfr/recorder/service/jfrPostBox.hpp"
  31 #include "jfr/recorder/service/jfrRecorderService.hpp"
  32 #include "jfr/utilities/jfrTypes.hpp"
  33 #include "logging/log.hpp"
  34 #include "memory/resourceArea.hpp"
  35 #include "runtime/atomic.hpp"
  36 #include "runtime/handles.inline.hpp"
  37 #include "runtime/globals.hpp"
  38 #include "runtime/mutexLocker.hpp"
  39 #include "runtime/os.hpp"
  40 #include "runtime/thread.inline.hpp"
  41 #include "utilities/growableArray.hpp"
  42 
  43 static const char vm_error_filename_fmt[] = "hs_err_pid%p.jfr";
  44 static const char vm_oom_filename_fmt[] = "hs_oom_pid%p.jfr";
  45 static const char vm_soe_filename_fmt[] = "hs_soe_pid%p.jfr";
  46 static const char chunk_file_jfr_ext[] = ".jfr";
  47 static const size_t iso8601_len = 19; // "YYYY-MM-DDTHH:MM:SS"
  48 


  49 static fio_fd open_exclusivly(const char* path) {
  50   return os::open(path, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
  51 }
  52 
  53 static int file_sort(const char** const file1, const char** file2) {
  54   assert(NULL != *file1 && NULL != *file2, "invariant");
  55   int cmp = strncmp(*file1, *file2, iso8601_len);
  56   if (0 == cmp) {
  57     const char* const dot1 = strchr(*file1, '.');
  58     assert(NULL != dot1, "invariant");
  59     const char* const dot2 = strchr(*file2, '.');
  60     assert(NULL != dot2, "invariant");
  61     ptrdiff_t file1_len = dot1 - *file1;
  62     ptrdiff_t file2_len = dot2 - *file2;
  63     if (file1_len < file2_len) {
  64       return -1;
  65     }
  66     if (file1_len > file2_len) {
  67       return 1;
  68     }


 230         int64_t bytes_read = 0;
 231         int64_t bytes_written = 0;
 232         while (bytes_read < current_filesize) {
 233           const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
 234           if (-1 == read_result) {
 235             log_info(jfr)( // For user, should not be "jfr, system"
 236               "Unable to recover JFR data");
 237             break;
 238           }
 239           bytes_read += (int64_t)read_result;
 240           assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
 241           bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
 242           assert(bytes_read == bytes_written, "invariant");
 243         }
 244         os::close(current_fd);
 245       }
 246     }
 247   }
 248 }
 249 
 250 static const char* create_emergency_dump_path() {
 251   char* buffer = NEW_RESOURCE_ARRAY_RETURN_NULL(char, JVM_MAXPATHLEN);
 252   if (NULL == buffer) {
 253     return NULL;
 254   }
 255   const char* const cwd = os::get_current_directory(buffer, JVM_MAXPATHLEN);

 256   if (NULL == cwd) {
 257     return NULL;
 258   }
 259   size_t pos = strlen(cwd);
 260   const int fsep_len = jio_snprintf(&buffer[pos], JVM_MAXPATHLEN - pos, "%s", os::file_separator());
 261   const char* filename_fmt = NULL;
 262   // fetch specific error cause
 263   switch (JfrJavaSupport::cause()) {
 264     case JfrJavaSupport::OUT_OF_MEMORY:
 265       filename_fmt = vm_oom_filename_fmt;
 266       break;
 267     case JfrJavaSupport::STACK_OVERFLOW:
 268       filename_fmt = vm_soe_filename_fmt;
 269       break;
 270     default:
 271       filename_fmt = vm_error_filename_fmt;
 272   }
 273   char* emergency_dump_path = NULL;
 274   pos += fsep_len;
 275   if (Arguments::copy_expand_pid(filename_fmt, strlen(filename_fmt), &buffer[pos], JVM_MAXPATHLEN - pos)) {
 276     const size_t emergency_filename_length = strlen(buffer);
 277     emergency_dump_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, emergency_filename_length + 1);
 278     if (NULL == emergency_dump_path) {
 279       return NULL;
 280     }
 281     strncpy(emergency_dump_path, buffer, emergency_filename_length + 1);
 282   }
 283   if (emergency_dump_path != NULL) {
 284     log_info(jfr)( // For user, should not be "jfr, system"
 285       "Attempting to recover JFR data, emergency jfr file: %s", emergency_dump_path);
 286   }
 287   return emergency_dump_path;
 288 }
 289 
 290 // Caller needs ResourceMark
 291 static const char* create_emergency_chunk_path(const char* repository_path) {
 292   assert(repository_path != NULL, "invariant");





 293   const size_t repository_path_len = strlen(repository_path);
 294   // date time
 295   char date_time_buffer[32] = { 0 };
 296   date_time(date_time_buffer, sizeof(date_time_buffer));
 297   size_t date_time_len = strlen(date_time_buffer);
 298   size_t chunkname_max_len = repository_path_len          // repository_base_path
 299                              + 1                          // "/"
 300                              + date_time_len              // date_time
 301                              + strlen(chunk_file_jfr_ext) // .jfr
 302                              + 1;
 303   char* chunk_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, chunkname_max_len);
 304   if (chunk_path == NULL) {
 305     return NULL;
 306   }
 307   // append the individual substrings
 308   jio_snprintf(chunk_path, chunkname_max_len, "%s%s%s%s", repository_path, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
 309   return chunk_path;
 310 }
 311 
 312 static fio_fd emergency_dump_file_descriptor() {
 313   ResourceMark rm;
 314   const char* const emergency_dump_path = create_emergency_dump_path();
 315   return emergency_dump_path != NULL ? open_exclusivly(emergency_dump_path) : invalid_fd;
 316 }
 317 
 318 const char* JfrEmergencyDump::build_dump_path(const char* repository_path) {
 319   return repository_path == NULL ? create_emergency_dump_path() : create_emergency_chunk_path(repository_path);
 320 }
 321 
 322 void JfrEmergencyDump::on_vm_error(const char* repository_path) {
 323   assert(repository_path != NULL, "invariant");
 324   ResourceMark rm;
 325   const fio_fd emergency_fd = emergency_dump_file_descriptor();
 326   if (emergency_fd != invalid_fd) {
 327     RepositoryIterator iterator(repository_path, strlen(repository_path));
 328     write_emergency_file(emergency_fd, iterator);
 329     os::close(emergency_fd);
 330   }
 331 }
 332 




  29 #include "jfr/recorder/repository/jfrEmergencyDump.hpp"
  30 #include "jfr/recorder/service/jfrPostBox.hpp"
  31 #include "jfr/recorder/service/jfrRecorderService.hpp"
  32 #include "jfr/utilities/jfrTypes.hpp"
  33 #include "logging/log.hpp"
  34 #include "memory/resourceArea.hpp"
  35 #include "runtime/atomic.hpp"
  36 #include "runtime/handles.inline.hpp"
  37 #include "runtime/globals.hpp"
  38 #include "runtime/mutexLocker.hpp"
  39 #include "runtime/os.hpp"
  40 #include "runtime/thread.inline.hpp"
  41 #include "utilities/growableArray.hpp"
  42 
  43 static const char vm_error_filename_fmt[] = "hs_err_pid%p.jfr";
  44 static const char vm_oom_filename_fmt[] = "hs_oom_pid%p.jfr";
  45 static const char vm_soe_filename_fmt[] = "hs_soe_pid%p.jfr";
  46 static const char chunk_file_jfr_ext[] = ".jfr";
  47 static const size_t iso8601_len = 19; // "YYYY-MM-DDTHH:MM:SS"
  48 
  49 char JfrEmergencyDump::_dump_path[JVM_MAXPATHLEN] = {0};
  50 
  51 static fio_fd open_exclusivly(const char* path) {
  52   return os::open(path, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
  53 }
  54 
  55 static int file_sort(const char** const file1, const char** file2) {
  56   assert(NULL != *file1 && NULL != *file2, "invariant");
  57   int cmp = strncmp(*file1, *file2, iso8601_len);
  58   if (0 == cmp) {
  59     const char* const dot1 = strchr(*file1, '.');
  60     assert(NULL != dot1, "invariant");
  61     const char* const dot2 = strchr(*file2, '.');
  62     assert(NULL != dot2, "invariant");
  63     ptrdiff_t file1_len = dot1 - *file1;
  64     ptrdiff_t file2_len = dot2 - *file2;
  65     if (file1_len < file2_len) {
  66       return -1;
  67     }
  68     if (file1_len > file2_len) {
  69       return 1;
  70     }


 232         int64_t bytes_read = 0;
 233         int64_t bytes_written = 0;
 234         while (bytes_read < current_filesize) {
 235           const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
 236           if (-1 == read_result) {
 237             log_info(jfr)( // For user, should not be "jfr, system"
 238               "Unable to recover JFR data");
 239             break;
 240           }
 241           bytes_read += (int64_t)read_result;
 242           assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
 243           bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
 244           assert(bytes_read == bytes_written, "invariant");
 245         }
 246         os::close(current_fd);
 247       }
 248     }
 249   }
 250 }
 251 
 252 const char* JfrEmergencyDump::create_emergency_dump_path() {
 253   if (*_dump_path != '\0') {
 254     return _dump_path;

 255   }
 256 
 257   const char* const cwd = os::get_current_directory(_dump_path, JVM_MAXPATHLEN);
 258   if (NULL == cwd) {
 259     return NULL;
 260   }
 261   size_t pos = strlen(cwd);
 262   const int fsep_len = jio_snprintf(&_dump_path[pos], JVM_MAXPATHLEN - pos, "%s", os::file_separator());
 263   const char* filename_fmt = NULL;
 264   // fetch specific error cause
 265   switch (JfrJavaSupport::cause()) {
 266     case JfrJavaSupport::OUT_OF_MEMORY:
 267       filename_fmt = vm_oom_filename_fmt;
 268       break;
 269     case JfrJavaSupport::STACK_OVERFLOW:
 270       filename_fmt = vm_soe_filename_fmt;
 271       break;
 272     default:
 273       filename_fmt = vm_error_filename_fmt;
 274   }

 275   pos += fsep_len;
 276   Arguments::copy_expand_pid(filename_fmt, strlen(filename_fmt), &_dump_path[pos], JVM_MAXPATHLEN - pos);
 277   if (*_dump_path != '\0') {







 278     log_info(jfr)( // For user, should not be "jfr, system"
 279       "Attempting to recover JFR data, emergency jfr file: %s", _dump_path);
 280   }
 281   return _dump_path;
 282 }
 283 
 284 // Caller needs ResourceMark
 285 const char* JfrEmergencyDump::create_emergency_chunk_path(const char* repository_path) {
 286   assert(repository_path != NULL, "invariant");
 287 
 288   if (*_dump_path != '\0') {
 289     return _dump_path;
 290   }
 291 
 292   const size_t repository_path_len = strlen(repository_path);
 293   // date time
 294   char date_time_buffer[32] = { 0 };
 295   date_time(date_time_buffer, sizeof(date_time_buffer));
 296   size_t date_time_len = strlen(date_time_buffer);
 297   size_t chunkname_max_len = repository_path_len          // repository_base_path
 298                              + 1                          // "/"
 299                              + date_time_len              // date_time
 300                              + strlen(chunk_file_jfr_ext) // .jfr
 301                              + 1;




 302   // append the individual substrings
 303   jio_snprintf(_dump_path, chunkname_max_len, "%s%s%s%s", repository_path, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
 304   return _dump_path;
 305 }
 306 
 307 fio_fd JfrEmergencyDump::emergency_dump_file_descriptor() {
 308   ResourceMark rm;
 309   const char* const emergency_dump_path = create_emergency_dump_path();
 310   return emergency_dump_path != NULL ? open_exclusivly(emergency_dump_path) : invalid_fd;
 311 }
 312 
 313 const char* JfrEmergencyDump::build_dump_path(const char* repository_path) {
 314   return repository_path == NULL ? create_emergency_dump_path() : create_emergency_chunk_path(repository_path);
 315 }
 316 
 317 void JfrEmergencyDump::on_vm_error(const char* repository_path) {
 318   assert(repository_path != NULL, "invariant");
 319   ResourceMark rm;
 320   const fio_fd emergency_fd = emergency_dump_file_descriptor();
 321   if (emergency_fd != invalid_fd) {
 322     RepositoryIterator iterator(repository_path, strlen(repository_path));
 323     write_emergency_file(emergency_fd, iterator);
 324     os::close(emergency_fd);
 325   }
 326 }
 327 


< prev index next >