8012260: ciReplay: Include PID into the name of replay data file
Reviewed-by: kvn, twisti
This commit is contained in:
parent
670aea401a
commit
f26c1a6c88
@ -1230,10 +1230,6 @@ bool os::dll_build_name(char* buffer, size_t buflen,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
|
||||||
return getcwd(buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if addr is inside libjvm.so
|
// check if addr is inside libjvm.so
|
||||||
bool os::address_is_in_vm(address addr) {
|
bool os::address_is_in_vm(address addr) {
|
||||||
static address libjvm_base_addr;
|
static address libjvm_base_addr;
|
||||||
|
@ -1662,10 +1662,6 @@ bool os::dll_build_name(char* buffer, size_t buflen,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
|
||||||
return getcwd(buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if addr is inside libjvm.so
|
// check if addr is inside libjvm.so
|
||||||
bool os::address_is_in_vm(address addr) {
|
bool os::address_is_in_vm(address addr) {
|
||||||
static address libjvm_base_addr;
|
static address libjvm_base_addr;
|
||||||
|
@ -251,3 +251,11 @@ bool os::has_allocatable_memory_limit(julong* limit) {
|
|||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* os::get_current_directory(char *buf, size_t buflen) {
|
||||||
|
return getcwd(buf, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* os::open(int fd, const char* mode) {
|
||||||
|
return ::fdopen(fd, mode);
|
||||||
|
}
|
||||||
|
@ -1915,10 +1915,6 @@ bool os::dll_build_name(char* buffer, size_t buflen,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
|
||||||
return getcwd(buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if addr is inside libjvm.so
|
// check if addr is inside libjvm.so
|
||||||
bool os::address_is_in_vm(address addr) {
|
bool os::address_is_in_vm(address addr) {
|
||||||
static address libjvm_base_addr;
|
static address libjvm_base_addr;
|
||||||
|
@ -1221,8 +1221,10 @@ bool os::dll_build_name(char *buffer, size_t buflen,
|
|||||||
|
|
||||||
// Needs to be in os specific directory because windows requires another
|
// Needs to be in os specific directory because windows requires another
|
||||||
// header file <direct.h>
|
// header file <direct.h>
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
const char* os::get_current_directory(char *buf, size_t buflen) {
|
||||||
return _getcwd(buf, buflen);
|
int n = static_cast<int>(buflen);
|
||||||
|
if (buflen > INT_MAX) n = INT_MAX;
|
||||||
|
return _getcwd(buf, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
@ -4098,6 +4100,10 @@ int os::open(const char *path, int oflag, int mode) {
|
|||||||
return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
|
return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* os::open(int fd, const char* mode) {
|
||||||
|
return ::_fdopen(fd, mode);
|
||||||
|
}
|
||||||
|
|
||||||
// Is a (classpath) directory empty?
|
// Is a (classpath) directory empty?
|
||||||
bool os::dir_is_empty(const char* path) {
|
bool os::dir_is_empty(const char* path) {
|
||||||
WIN32_FIND_DATA fd;
|
WIN32_FIND_DATA fd;
|
||||||
|
@ -1149,23 +1149,9 @@ void ciEnv::record_out_of_memory_failure() {
|
|||||||
record_method_not_compilable("out of memory");
|
record_method_not_compilable("out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
fileStream* ciEnv::_replay_data_stream = NULL;
|
void ciEnv::dump_replay_data(outputStream* out) {
|
||||||
|
|
||||||
void ciEnv::dump_replay_data() {
|
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
MutexLocker ml(Compile_lock);
|
MutexLocker ml(Compile_lock);
|
||||||
if (_replay_data_stream == NULL) {
|
|
||||||
_replay_data_stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(ReplayDataFile);
|
|
||||||
if (_replay_data_stream == NULL) {
|
|
||||||
fatal(err_msg("Can't open %s for replay data", ReplayDataFile));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dump_replay_data(_replay_data_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ciEnv::dump_replay_data(outputStream* out) {
|
|
||||||
ASSERT_IN_VM;
|
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables);
|
out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables);
|
||||||
|
@ -46,8 +46,6 @@ class ciEnv : StackObj {
|
|||||||
friend class CompileBroker;
|
friend class CompileBroker;
|
||||||
friend class Dependencies; // for get_object, during logging
|
friend class Dependencies; // for get_object, during logging
|
||||||
|
|
||||||
static fileStream* _replay_data_stream;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects()
|
Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects()
|
||||||
Arena _ciEnv_arena;
|
Arena _ciEnv_arena;
|
||||||
@ -451,10 +449,6 @@ public:
|
|||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
|
void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
|
||||||
|
|
||||||
// Dump the compilation replay data for this ciEnv to
|
|
||||||
// ReplayDataFile, creating the file if needed.
|
|
||||||
void dump_replay_data();
|
|
||||||
|
|
||||||
// Dump the compilation replay data for the ciEnv to the stream.
|
// Dump the compilation replay data for the ciEnv to the stream.
|
||||||
void dump_replay_data(outputStream* out);
|
void dump_replay_data(outputStream* out);
|
||||||
};
|
};
|
||||||
|
@ -89,7 +89,7 @@ class CompileReplay : public StackObj {
|
|||||||
loader = Handle(thread, SystemDictionary::java_system_loader());
|
loader = Handle(thread, SystemDictionary::java_system_loader());
|
||||||
stream = fopen(filename, "rt");
|
stream = fopen(filename, "rt");
|
||||||
if (stream == NULL) {
|
if (stream == NULL) {
|
||||||
fprintf(stderr, "Can't open replay file %s\n", filename);
|
fprintf(stderr, "ERROR: Can't open replay file %s\n", filename);
|
||||||
}
|
}
|
||||||
buffer_length = 32;
|
buffer_length = 32;
|
||||||
buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
|
buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
|
||||||
@ -327,7 +327,6 @@ class CompileReplay : public StackObj {
|
|||||||
if (had_error()) {
|
if (had_error()) {
|
||||||
tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
|
tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
|
||||||
tty->print_cr("%s", buffer);
|
tty->print_cr("%s", buffer);
|
||||||
assert(false, "error");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pos = 0;
|
pos = 0;
|
||||||
@ -551,7 +550,7 @@ class CompileReplay : public StackObj {
|
|||||||
if (parsed_two_word == i) continue;
|
if (parsed_two_word == i) continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
fatal(err_msg_res("Unexpected tag: %d", cp->tag_at(i).value()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,6 +818,11 @@ int ciReplay::replay_impl(TRAPS) {
|
|||||||
ReplaySuppressInitializers = 1;
|
ReplaySuppressInitializers = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAG_IS_DEFAULT(ReplayDataFile)) {
|
||||||
|
tty->print_cr("ERROR: no compiler replay data file specified (use -XX:ReplayDataFile=replay_pid12345.txt).");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Load and parse the replay data
|
// Load and parse the replay data
|
||||||
CompileReplay rp(ReplayDataFile, THREAD);
|
CompileReplay rp(ReplayDataFile, THREAD);
|
||||||
int exit_code = 0;
|
int exit_code = 0;
|
||||||
|
@ -3223,8 +3223,9 @@ class CommandLineFlags {
|
|||||||
develop(bool, ReplayCompiles, false, \
|
develop(bool, ReplayCompiles, false, \
|
||||||
"Enable replay of compilations from ReplayDataFile") \
|
"Enable replay of compilations from ReplayDataFile") \
|
||||||
\
|
\
|
||||||
develop(ccstr, ReplayDataFile, "replay.txt", \
|
product(ccstr, ReplayDataFile, NULL, \
|
||||||
"file containing compilation replay information") \
|
"File containing compilation replay information" \
|
||||||
|
"[default: ./replay_pid%p.log] (%p replaced with pid)") \
|
||||||
\
|
\
|
||||||
develop(intx, ReplaySuppressInitializers, 2, \
|
develop(intx, ReplaySuppressInitializers, 2, \
|
||||||
"Controls handling of class initialization during replay" \
|
"Controls handling of class initialization during replay" \
|
||||||
@ -3237,8 +3238,8 @@ class CommandLineFlags {
|
|||||||
develop(bool, ReplayIgnoreInitErrors, false, \
|
develop(bool, ReplayIgnoreInitErrors, false, \
|
||||||
"Ignore exceptions thrown during initialization for replay") \
|
"Ignore exceptions thrown during initialization for replay") \
|
||||||
\
|
\
|
||||||
develop(bool, DumpReplayDataOnError, true, \
|
product(bool, DumpReplayDataOnError, true, \
|
||||||
"record replay data for crashing compiler threads") \
|
"Record replay data for crashing compiler threads") \
|
||||||
\
|
\
|
||||||
product(bool, CICompilerCountPerCPU, false, \
|
product(bool, CICompilerCountPerCPU, false, \
|
||||||
"1 compiler thread for log(N CPUs)") \
|
"1 compiler thread for log(N CPUs)") \
|
||||||
|
@ -454,6 +454,7 @@ class os: AllStatic {
|
|||||||
// File i/o operations
|
// File i/o operations
|
||||||
static const int default_file_open_flags();
|
static const int default_file_open_flags();
|
||||||
static int open(const char *path, int oflag, int mode);
|
static int open(const char *path, int oflag, int mode);
|
||||||
|
static FILE* open(int fd, const char* mode);
|
||||||
static int close(int fd);
|
static int close(int fd);
|
||||||
static jlong lseek(int fd, jlong offset, int whence);
|
static jlong lseek(int fd, jlong offset, int whence);
|
||||||
static char* native_path(char *path);
|
static char* native_path(char *path);
|
||||||
@ -477,7 +478,7 @@ class os: AllStatic {
|
|||||||
static const char* dll_file_extension();
|
static const char* dll_file_extension();
|
||||||
|
|
||||||
static const char* get_temp_directory();
|
static const char* get_temp_directory();
|
||||||
static const char* get_current_directory(char *buf, int buflen);
|
static const char* get_current_directory(char *buf, size_t buflen);
|
||||||
|
|
||||||
// Builds a platform-specific full library path given a ld path and lib name
|
// Builds a platform-specific full library path given a ld path and lib name
|
||||||
// Returns true if buffer contains full path to existing file, false otherwise
|
// Returns true if buffer contains full path to existing file, false otherwise
|
||||||
|
@ -196,7 +196,7 @@ class fileStream : public outputStream {
|
|||||||
fileStream() { _file = NULL; _need_close = false; }
|
fileStream() { _file = NULL; _need_close = false; }
|
||||||
fileStream(const char* file_name);
|
fileStream(const char* file_name);
|
||||||
fileStream(const char* file_name, const char* opentype);
|
fileStream(const char* file_name, const char* opentype);
|
||||||
fileStream(FILE* file) { _file = file; _need_close = false; }
|
fileStream(FILE* file, bool need_close = false) { _file = file; _need_close = need_close; }
|
||||||
~fileStream();
|
~fileStream();
|
||||||
bool is_open() const { return _file != NULL; }
|
bool is_open() const { return _file != NULL; }
|
||||||
void set_need_close(bool b) { _need_close = b;}
|
void set_need_close(bool b) { _need_close = b;}
|
||||||
|
@ -796,6 +796,56 @@ void VMError::report(outputStream* st) {
|
|||||||
VMError* volatile VMError::first_error = NULL;
|
VMError* volatile VMError::first_error = NULL;
|
||||||
volatile jlong VMError::first_error_tid = -1;
|
volatile jlong VMError::first_error_tid = -1;
|
||||||
|
|
||||||
|
/** Expand a pattern into a buffer starting at pos and open a file using constructed path */
|
||||||
|
static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) {
|
||||||
|
int fd = -1;
|
||||||
|
if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) {
|
||||||
|
fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, char* buf, size_t buflen) {
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
// If possible, use specified pattern to construct log file name
|
||||||
|
if (pattern != NULL) {
|
||||||
|
fd = expand_and_open(pattern, buf, buflen, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Either user didn't specify, or the user's location failed,
|
||||||
|
// so use the default name in the current directory
|
||||||
|
if (fd == -1) {
|
||||||
|
const char* cwd = os::get_current_directory(buf, buflen);
|
||||||
|
if (cwd != NULL) {
|
||||||
|
size_t pos = strlen(cwd);
|
||||||
|
int fsep_len = jio_snprintf(&buf[pos], buflen-pos, "%s", os::file_separator());
|
||||||
|
pos += fsep_len;
|
||||||
|
if (fsep_len > 0) {
|
||||||
|
fd = expand_and_open(default_pattern, buf, buflen, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try temp directory if it exists.
|
||||||
|
if (fd == -1) {
|
||||||
|
const char* tmpdir = os::get_temp_directory();
|
||||||
|
if (tmpdir != NULL && strlen(tmpdir) > 0) {
|
||||||
|
int pos = jio_snprintf(buf, buflen, "%s%s", tmpdir, os::file_separator());
|
||||||
|
if (pos > 0) {
|
||||||
|
fd = expand_and_open(default_pattern, buf, buflen, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
void VMError::report_and_die() {
|
void VMError::report_and_die() {
|
||||||
// Don't allocate large buffer on stack
|
// Don't allocate large buffer on stack
|
||||||
static char buffer[O_BUFLEN];
|
static char buffer[O_BUFLEN];
|
||||||
@ -905,36 +955,7 @@ void VMError::report_and_die() {
|
|||||||
// see if log file is already open
|
// see if log file is already open
|
||||||
if (!log.is_open()) {
|
if (!log.is_open()) {
|
||||||
// open log file
|
// open log file
|
||||||
int fd = -1;
|
int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (ErrorFile != NULL) {
|
|
||||||
bool copy_ok =
|
|
||||||
Arguments::copy_expand_pid(ErrorFile, strlen(ErrorFile), buffer, sizeof(buffer));
|
|
||||||
if (copy_ok) {
|
|
||||||
fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == -1) {
|
|
||||||
const char *cwd = os::get_current_directory(buffer, sizeof(buffer));
|
|
||||||
size_t len = strlen(cwd);
|
|
||||||
// either user didn't specify, or the user's location failed,
|
|
||||||
// so use the default name in the current directory
|
|
||||||
jio_snprintf(&buffer[len], sizeof(buffer)-len, "%shs_err_pid%u.log",
|
|
||||||
os::file_separator(), os::current_process_id());
|
|
||||||
fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == -1) {
|
|
||||||
const char * tmpdir = os::get_temp_directory();
|
|
||||||
// try temp directory if it exists.
|
|
||||||
if (tmpdir != NULL && tmpdir[0] != '\0') {
|
|
||||||
jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
|
|
||||||
tmpdir, os::file_separator(), os::current_process_id());
|
|
||||||
fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
out.print_raw("# An error report file with more information is saved as:\n# ");
|
out.print_raw("# An error report file with more information is saved as:\n# ");
|
||||||
out.print_raw_cr(buffer);
|
out.print_raw_cr(buffer);
|
||||||
@ -958,7 +979,7 @@ void VMError::report_and_die() {
|
|||||||
// Run error reporting to determine whether or not to report the crash.
|
// Run error reporting to determine whether or not to report the crash.
|
||||||
if (!transmit_report_done && should_report_bug(first_error->_id)) {
|
if (!transmit_report_done && should_report_bug(first_error->_id)) {
|
||||||
transmit_report_done = true;
|
transmit_report_done = true;
|
||||||
FILE* hs_err = ::fdopen(log.fd(), "r");
|
FILE* hs_err = os::open(log.fd(), "r");
|
||||||
if (NULL != hs_err) {
|
if (NULL != hs_err) {
|
||||||
ErrorReporter er;
|
ErrorReporter er;
|
||||||
er.call(hs_err, buffer, O_BUFLEN);
|
er.call(hs_err, buffer, O_BUFLEN);
|
||||||
@ -1008,7 +1029,19 @@ void VMError::report_and_die() {
|
|||||||
skip_replay = true;
|
skip_replay = true;
|
||||||
ciEnv* env = ciEnv::current();
|
ciEnv* env = ciEnv::current();
|
||||||
if (env != NULL) {
|
if (env != NULL) {
|
||||||
env->dump_replay_data();
|
int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", buffer, sizeof(buffer));
|
||||||
|
if (fd != -1) {
|
||||||
|
FILE* replay_data_file = os::open(fd, "w");
|
||||||
|
if (replay_data_file != NULL) {
|
||||||
|
fileStream replay_data_stream(replay_data_file, /*need_close=*/true);
|
||||||
|
env->dump_replay_data(&replay_data_stream);
|
||||||
|
out.print_raw("#\n# Compiler replay data is saved as:\n# ");
|
||||||
|
out.print_raw_cr(buffer);
|
||||||
|
} else {
|
||||||
|
out.print_raw("#\n# Can't open file to dump replay data. Error: ");
|
||||||
|
out.print_raw_cr(strerror(os::get_last_error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user