mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-12 22:50:08 +00:00
8269416: [JVMCI] capture libjvmci crash data to a file
Reviewed-by: kvn, dholmes
This commit is contained in:
parent
a0f32cb140
commit
a6b253d85c
@ -34,6 +34,7 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
|
||||
JVMCIRuntime* JVMCI::_compiler_runtime = NULL;
|
||||
@ -45,6 +46,9 @@ char* JVMCI::_shared_library_path = NULL;
|
||||
volatile bool JVMCI::_in_shutdown = false;
|
||||
StringEventLog* JVMCI::_events = NULL;
|
||||
StringEventLog* JVMCI::_verbose_events = NULL;
|
||||
volatile intx JVMCI::_fatal_log_init_thread = -1;
|
||||
volatile int JVMCI::_fatal_log_fd = -1;
|
||||
const char* JVMCI::_fatal_log_filename = NULL;
|
||||
|
||||
void jvmci_vmStructs_init() NOT_DEBUG_RETURN;
|
||||
|
||||
@ -211,6 +215,45 @@ bool JVMCI::in_shutdown() {
|
||||
return _in_shutdown;
|
||||
}
|
||||
|
||||
void JVMCI::fatal_log(const char* buf, size_t count) {
|
||||
intx current_thread_id = os::current_thread_id();
|
||||
intx invalid_id = -1;
|
||||
int log_fd;
|
||||
if (_fatal_log_init_thread == invalid_id && Atomic::cmpxchg(&_fatal_log_init_thread, invalid_id, current_thread_id) == invalid_id) {
|
||||
if (ErrorFileToStdout) {
|
||||
log_fd = 1;
|
||||
} else if (ErrorFileToStderr) {
|
||||
log_fd = 2;
|
||||
} else {
|
||||
static char name_buffer[O_BUFLEN];
|
||||
log_fd = VMError::prepare_log_file(JVMCINativeLibraryErrorFile, LIBJVMCI_ERR_FILE, true, name_buffer, sizeof(name_buffer));
|
||||
if (log_fd != -1) {
|
||||
_fatal_log_filename = name_buffer;
|
||||
} else {
|
||||
int e = errno;
|
||||
tty->print("Can't open JVMCI shared library error report file. Error: ");
|
||||
tty->print_raw_cr(os::strerror(e));
|
||||
tty->print_cr("JVMCI shared library error report will be written to console.");
|
||||
|
||||
// See notes in VMError::report_and_die about hard coding tty to 1
|
||||
log_fd = 1;
|
||||
}
|
||||
}
|
||||
_fatal_log_fd = log_fd;
|
||||
} else {
|
||||
// Another thread won the race to initialize the stream. Give it time
|
||||
// to complete initialization. VM locks cannot be used as the current
|
||||
// thread might not be attached to the VM (e.g. a native thread started
|
||||
// within libjvmci).
|
||||
while (_fatal_log_fd == -1) {
|
||||
os::naked_short_sleep(50);
|
||||
}
|
||||
}
|
||||
fdStream log(_fatal_log_fd);
|
||||
log.write(buf, count);
|
||||
log.flush();
|
||||
}
|
||||
|
||||
void JVMCI::vlog(int level, const char* format, va_list ap) {
|
||||
if (LogEvents && JVMCIEventLogLevel >= level) {
|
||||
StringEventLog* events = level == 1 ? _events : _verbose_events;
|
||||
|
||||
@ -74,6 +74,16 @@ class JVMCI : public AllStatic {
|
||||
// Access to the HotSpot heap based JVMCIRuntime
|
||||
static JVMCIRuntime* _java_runtime;
|
||||
|
||||
// The file descriptor to which fatal_log() writes. Initialized on
|
||||
// first call to fatal_log().
|
||||
static volatile int _fatal_log_fd;
|
||||
|
||||
// The path of the file underlying _fatal_log_fd if it is a normal file.
|
||||
static const char* _fatal_log_filename;
|
||||
|
||||
// Native thread id of thread that will initialize _fatal_log_fd.
|
||||
static volatile intx _fatal_log_init_thread;
|
||||
|
||||
// JVMCI event log (shows up in hs_err crash logs).
|
||||
static StringEventLog* _events;
|
||||
static StringEventLog* _verbose_events;
|
||||
@ -100,6 +110,13 @@ class JVMCI : public AllStatic {
|
||||
// `load` is true then JVMCI_lock must be locked.
|
||||
static void* get_shared_library(char*& path, bool load);
|
||||
|
||||
// Logs the fatal crash data in `buf` to the appropriate stream.
|
||||
static void fatal_log(const char* buf, size_t count);
|
||||
|
||||
// Gets the name of the opened JVMCI shared library crash data file or NULL
|
||||
// if this file has not been created.
|
||||
static const char* fatal_log_filename() { return _fatal_log_filename; }
|
||||
|
||||
static void do_unloading(bool unloading_occurred);
|
||||
|
||||
static void metadata_do(void f(Metadata*));
|
||||
|
||||
@ -891,6 +891,12 @@ static void _log(const char* buf, size_t count) {
|
||||
tty->write((char*) buf, count);
|
||||
}
|
||||
|
||||
// Function for redirecting shared library JavaVM fatal error data to a log file.
|
||||
// The log file is opened on first call to this function.
|
||||
static void _fatal_log(const char* buf, size_t count) {
|
||||
JVMCI::fatal_log(buf, count);
|
||||
}
|
||||
|
||||
// Function for shared library JavaVM to flush tty
|
||||
static void _flush_log() {
|
||||
tty->flush();
|
||||
@ -898,7 +904,8 @@ static void _flush_log() {
|
||||
|
||||
// Function for shared library JavaVM to exit HotSpot on a fatal error
|
||||
static void _fatal() {
|
||||
fatal("Fatal error in JVMCI shared library");
|
||||
intx current_thread_id = os::current_thread_id();
|
||||
fatal("thread " INTX_FORMAT ": Fatal error in JVMCI shared library", current_thread_id);
|
||||
}
|
||||
|
||||
JNIEnv* JVMCIRuntime::init_shared_library_javavm() {
|
||||
@ -925,7 +932,7 @@ JNIEnv* JVMCIRuntime::init_shared_library_javavm() {
|
||||
JavaVMInitArgs vm_args;
|
||||
vm_args.version = JNI_VERSION_1_2;
|
||||
vm_args.ignoreUnrecognized = JNI_TRUE;
|
||||
JavaVMOption options[4];
|
||||
JavaVMOption options[5];
|
||||
jlong javaVM_id = 0;
|
||||
|
||||
// Protocol: JVMCI shared library JavaVM should support a non-standard "_javavm_id"
|
||||
@ -940,6 +947,8 @@ JNIEnv* JVMCIRuntime::init_shared_library_javavm() {
|
||||
options[2].extraInfo = (void*) _flush_log;
|
||||
options[3].optionString = (char*) "_fatal";
|
||||
options[3].extraInfo = (void*) _fatal;
|
||||
options[4].optionString = (char*) "_fatal_log";
|
||||
options[4].extraInfo = (void*) _fatal_log;
|
||||
|
||||
vm_args.version = JNI_VERSION_1_2;
|
||||
vm_args.options = options;
|
||||
|
||||
@ -121,6 +121,7 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
|
||||
CHECK_NOT_SET(JVMCIPrintProperties, EnableJVMCI)
|
||||
CHECK_NOT_SET(UseJVMCINativeLibrary, EnableJVMCI)
|
||||
CHECK_NOT_SET(JVMCILibPath, EnableJVMCI)
|
||||
CHECK_NOT_SET(JVMCINativeLibraryErrorFile, EnableJVMCI)
|
||||
CHECK_NOT_SET(JVMCILibDumpJNIConfig, EnableJVMCI)
|
||||
|
||||
#ifndef COMPILER2
|
||||
@ -176,6 +177,7 @@ bool JVMCIGlobals::enable_jvmci_product_mode(JVMFlagOrigin origin) {
|
||||
"JVMCILibPath",
|
||||
"JVMCILibDumpJNIConfig",
|
||||
"UseJVMCINativeLibrary",
|
||||
"JVMCINativeLibraryErrorFile",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
|
||||
class fileStream;
|
||||
|
||||
#define LIBJVMCI_ERR_FILE "hs_err_pid%p_libjvmci.log"
|
||||
|
||||
//
|
||||
// Declare all global flags used by the JVMCI compiler. Only flags that need
|
||||
// to be accessible to the JVMCI C++ code should be defined here.
|
||||
@ -123,6 +125,11 @@ class fileStream;
|
||||
"on the HotSpot heap. Defaults to true if EnableJVMCIProduct is " \
|
||||
"true and a JVMCI native library is available.") \
|
||||
\
|
||||
product(ccstr, JVMCINativeLibraryErrorFile, NULL, EXPERIMENTAL, \
|
||||
"If an error in the JVMCI native library occurs, save the " \
|
||||
"error data to this file" \
|
||||
"[default: ./" LIBJVMCI_ERR_FILE "] (%p replaced with pid)") \
|
||||
\
|
||||
NOT_COMPILER2(product(bool, UseMultiplyToLenIntrinsic, false, DIAGNOSTIC, \
|
||||
"Enables intrinsification of BigInteger.multiplyToLen()")) \
|
||||
\
|
||||
|
||||
@ -63,6 +63,9 @@
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfr.hpp"
|
||||
#endif
|
||||
#if INCLUDE_JVMCI
|
||||
#include "jvmci/jvmci.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
#include <signal.h>
|
||||
@ -1273,7 +1276,7 @@ static int expand_and_open(const char* pattern, bool overwrite_existing, char* b
|
||||
* Name and location depends on pattern, default_pattern params and access
|
||||
* permissions.
|
||||
*/
|
||||
static int prepare_log_file(const char* pattern, const char* default_pattern, bool overwrite_existing, char* buf, size_t buflen) {
|
||||
int VMError::prepare_log_file(const char* pattern, const char* default_pattern, bool overwrite_existing, char* buf, size_t buflen) {
|
||||
int fd = -1;
|
||||
|
||||
// If possible, use specified pattern to construct log file name
|
||||
@ -1584,6 +1587,13 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
if (JVMCI::fatal_log_filename() != NULL) {
|
||||
out.print_raw("#\n# The JVMCI shared library error report file is saved as:\n# ");
|
||||
out.print_raw_cr(JVMCI::fatal_log_filename());
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool skip_bug_url = !should_submit_bug_report(_id);
|
||||
if (!skip_bug_url) {
|
||||
skip_bug_url = true;
|
||||
|
||||
@ -184,5 +184,10 @@ public:
|
||||
// Needed when printing signal handlers.
|
||||
NOT_WINDOWS(static const void* crash_handler_address;)
|
||||
|
||||
// Construct file name for a log file and return it's file descriptor.
|
||||
// Name and location depends on pattern, default_pattern params and access
|
||||
// permissions.
|
||||
static int prepare_log_file(const char* pattern, const char* default_pattern, bool overwrite_existing, char* buf, size_t buflen);
|
||||
|
||||
};
|
||||
#endif // SHARE_UTILITIES_VMERROR_HPP
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user