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 } |