Thu, 25 Apr 2013 11:02:32 -0700
8012260: ciReplay: Include PID into the name of replay data file
Reviewed-by: kvn, twisti
1.1 --- a/src/os/bsd/vm/os_bsd.cpp Wed Apr 24 18:20:04 2013 -0400 1.2 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Apr 25 11:02:32 2013 -0700 1.3 @@ -1230,10 +1230,6 @@ 1.4 return retval; 1.5 } 1.6 1.7 -const char* os::get_current_directory(char *buf, int buflen) { 1.8 - return getcwd(buf, buflen); 1.9 -} 1.10 - 1.11 // check if addr is inside libjvm.so 1.12 bool os::address_is_in_vm(address addr) { 1.13 static address libjvm_base_addr;
2.1 --- a/src/os/linux/vm/os_linux.cpp Wed Apr 24 18:20:04 2013 -0400 2.2 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 25 11:02:32 2013 -0700 2.3 @@ -1662,10 +1662,6 @@ 2.4 return retval; 2.5 } 2.6 2.7 -const char* os::get_current_directory(char *buf, int buflen) { 2.8 - return getcwd(buf, buflen); 2.9 -} 2.10 - 2.11 // check if addr is inside libjvm.so 2.12 bool os::address_is_in_vm(address addr) { 2.13 static address libjvm_base_addr;
3.1 --- a/src/os/posix/vm/os_posix.cpp Wed Apr 24 18:20:04 2013 -0400 3.2 +++ b/src/os/posix/vm/os_posix.cpp Thu Apr 25 11:02:32 2013 -0700 3.3 @@ -251,3 +251,11 @@ 3.4 return true; 3.5 #endif 3.6 } 3.7 + 3.8 +const char* os::get_current_directory(char *buf, size_t buflen) { 3.9 + return getcwd(buf, buflen); 3.10 +} 3.11 + 3.12 +FILE* os::open(int fd, const char* mode) { 3.13 + return ::fdopen(fd, mode); 3.14 +}
4.1 --- a/src/os/solaris/vm/os_solaris.cpp Wed Apr 24 18:20:04 2013 -0400 4.2 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Apr 25 11:02:32 2013 -0700 4.3 @@ -1915,10 +1915,6 @@ 4.4 return retval; 4.5 } 4.6 4.7 -const char* os::get_current_directory(char *buf, int buflen) { 4.8 - return getcwd(buf, buflen); 4.9 -} 4.10 - 4.11 // check if addr is inside libjvm.so 4.12 bool os::address_is_in_vm(address addr) { 4.13 static address libjvm_base_addr;
5.1 --- a/src/os/windows/vm/os_windows.cpp Wed Apr 24 18:20:04 2013 -0400 5.2 +++ b/src/os/windows/vm/os_windows.cpp Thu Apr 25 11:02:32 2013 -0700 5.3 @@ -1221,8 +1221,10 @@ 5.4 5.5 // Needs to be in os specific directory because windows requires another 5.6 // header file <direct.h> 5.7 -const char* os::get_current_directory(char *buf, int buflen) { 5.8 - return _getcwd(buf, buflen); 5.9 +const char* os::get_current_directory(char *buf, size_t buflen) { 5.10 + int n = static_cast<int>(buflen); 5.11 + if (buflen > INT_MAX) n = INT_MAX; 5.12 + return _getcwd(buf, n); 5.13 } 5.14 5.15 //----------------------------------------------------------- 5.16 @@ -4098,6 +4100,10 @@ 5.17 return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); 5.18 } 5.19 5.20 +FILE* os::open(int fd, const char* mode) { 5.21 + return ::_fdopen(fd, mode); 5.22 +} 5.23 + 5.24 // Is a (classpath) directory empty? 5.25 bool os::dir_is_empty(const char* path) { 5.26 WIN32_FIND_DATA fd;
6.1 --- a/src/share/vm/ci/ciEnv.cpp Wed Apr 24 18:20:04 2013 -0400 6.2 +++ b/src/share/vm/ci/ciEnv.cpp Thu Apr 25 11:02:32 2013 -0700 6.3 @@ -1149,23 +1149,9 @@ 6.4 record_method_not_compilable("out of memory"); 6.5 } 6.6 6.7 -fileStream* ciEnv::_replay_data_stream = NULL; 6.8 - 6.9 -void ciEnv::dump_replay_data() { 6.10 +void ciEnv::dump_replay_data(outputStream* out) { 6.11 VM_ENTRY_MARK; 6.12 MutexLocker ml(Compile_lock); 6.13 - if (_replay_data_stream == NULL) { 6.14 - _replay_data_stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(ReplayDataFile); 6.15 - if (_replay_data_stream == NULL) { 6.16 - fatal(err_msg("Can't open %s for replay data", ReplayDataFile)); 6.17 - } 6.18 - } 6.19 - dump_replay_data(_replay_data_stream); 6.20 -} 6.21 - 6.22 - 6.23 -void ciEnv::dump_replay_data(outputStream* out) { 6.24 - ASSERT_IN_VM; 6.25 ResourceMark rm; 6.26 #if INCLUDE_JVMTI 6.27 out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables);
7.1 --- a/src/share/vm/ci/ciEnv.hpp Wed Apr 24 18:20:04 2013 -0400 7.2 +++ b/src/share/vm/ci/ciEnv.hpp Thu Apr 25 11:02:32 2013 -0700 7.3 @@ -46,8 +46,6 @@ 7.4 friend class CompileBroker; 7.5 friend class Dependencies; // for get_object, during logging 7.6 7.7 - static fileStream* _replay_data_stream; 7.8 - 7.9 private: 7.10 Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects() 7.11 Arena _ciEnv_arena; 7.12 @@ -451,10 +449,6 @@ 7.13 // RedefineClasses support 7.14 void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); } 7.15 7.16 - // Dump the compilation replay data for this ciEnv to 7.17 - // ReplayDataFile, creating the file if needed. 7.18 - void dump_replay_data(); 7.19 - 7.20 // Dump the compilation replay data for the ciEnv to the stream. 7.21 void dump_replay_data(outputStream* out); 7.22 };
8.1 --- a/src/share/vm/ci/ciReplay.cpp Wed Apr 24 18:20:04 2013 -0400 8.2 +++ b/src/share/vm/ci/ciReplay.cpp Thu Apr 25 11:02:32 2013 -0700 8.3 @@ -89,7 +89,7 @@ 8.4 loader = Handle(thread, SystemDictionary::java_system_loader()); 8.5 stream = fopen(filename, "rt"); 8.6 if (stream == NULL) { 8.7 - fprintf(stderr, "Can't open replay file %s\n", filename); 8.8 + fprintf(stderr, "ERROR: Can't open replay file %s\n", filename); 8.9 } 8.10 buffer_length = 32; 8.11 buffer = NEW_RESOURCE_ARRAY(char, buffer_length); 8.12 @@ -327,7 +327,6 @@ 8.13 if (had_error()) { 8.14 tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message); 8.15 tty->print_cr("%s", buffer); 8.16 - assert(false, "error"); 8.17 return; 8.18 } 8.19 pos = 0; 8.20 @@ -551,7 +550,7 @@ 8.21 if (parsed_two_word == i) continue; 8.22 8.23 default: 8.24 - ShouldNotReachHere(); 8.25 + fatal(err_msg_res("Unexpected tag: %d", cp->tag_at(i).value())); 8.26 break; 8.27 } 8.28 8.29 @@ -819,6 +818,11 @@ 8.30 ReplaySuppressInitializers = 1; 8.31 } 8.32 8.33 + if (FLAG_IS_DEFAULT(ReplayDataFile)) { 8.34 + tty->print_cr("ERROR: no compiler replay data file specified (use -XX:ReplayDataFile=replay_pid12345.txt)."); 8.35 + return 1; 8.36 + } 8.37 + 8.38 // Load and parse the replay data 8.39 CompileReplay rp(ReplayDataFile, THREAD); 8.40 int exit_code = 0;
9.1 --- a/src/share/vm/runtime/globals.hpp Wed Apr 24 18:20:04 2013 -0400 9.2 +++ b/src/share/vm/runtime/globals.hpp Thu Apr 25 11:02:32 2013 -0700 9.3 @@ -3223,8 +3223,9 @@ 9.4 develop(bool, ReplayCompiles, false, \ 9.5 "Enable replay of compilations from ReplayDataFile") \ 9.6 \ 9.7 - develop(ccstr, ReplayDataFile, "replay.txt", \ 9.8 - "file containing compilation replay information") \ 9.9 + product(ccstr, ReplayDataFile, NULL, \ 9.10 + "File containing compilation replay information" \ 9.11 + "[default: ./replay_pid%p.log] (%p replaced with pid)") \ 9.12 \ 9.13 develop(intx, ReplaySuppressInitializers, 2, \ 9.14 "Controls handling of class initialization during replay" \ 9.15 @@ -3237,8 +3238,8 @@ 9.16 develop(bool, ReplayIgnoreInitErrors, false, \ 9.17 "Ignore exceptions thrown during initialization for replay") \ 9.18 \ 9.19 - develop(bool, DumpReplayDataOnError, true, \ 9.20 - "record replay data for crashing compiler threads") \ 9.21 + product(bool, DumpReplayDataOnError, true, \ 9.22 + "Record replay data for crashing compiler threads") \ 9.23 \ 9.24 product(bool, CICompilerCountPerCPU, false, \ 9.25 "1 compiler thread for log(N CPUs)") \
10.1 --- a/src/share/vm/runtime/os.hpp Wed Apr 24 18:20:04 2013 -0400 10.2 +++ b/src/share/vm/runtime/os.hpp Thu Apr 25 11:02:32 2013 -0700 10.3 @@ -454,6 +454,7 @@ 10.4 // File i/o operations 10.5 static const int default_file_open_flags(); 10.6 static int open(const char *path, int oflag, int mode); 10.7 + static FILE* open(int fd, const char* mode); 10.8 static int close(int fd); 10.9 static jlong lseek(int fd, jlong offset, int whence); 10.10 static char* native_path(char *path); 10.11 @@ -477,7 +478,7 @@ 10.12 static const char* dll_file_extension(); 10.13 10.14 static const char* get_temp_directory(); 10.15 - static const char* get_current_directory(char *buf, int buflen); 10.16 + static const char* get_current_directory(char *buf, size_t buflen); 10.17 10.18 // Builds a platform-specific full library path given a ld path and lib name 10.19 // Returns true if buffer contains full path to existing file, false otherwise
11.1 --- a/src/share/vm/utilities/ostream.hpp Wed Apr 24 18:20:04 2013 -0400 11.2 +++ b/src/share/vm/utilities/ostream.hpp Thu Apr 25 11:02:32 2013 -0700 11.3 @@ -196,7 +196,7 @@ 11.4 fileStream() { _file = NULL; _need_close = false; } 11.5 fileStream(const char* file_name); 11.6 fileStream(const char* file_name, const char* opentype); 11.7 - fileStream(FILE* file) { _file = file; _need_close = false; } 11.8 + fileStream(FILE* file, bool need_close = false) { _file = file; _need_close = need_close; } 11.9 ~fileStream(); 11.10 bool is_open() const { return _file != NULL; } 11.11 void set_need_close(bool b) { _need_close = b;}
12.1 --- a/src/share/vm/utilities/vmError.cpp Wed Apr 24 18:20:04 2013 -0400 12.2 +++ b/src/share/vm/utilities/vmError.cpp Thu Apr 25 11:02:32 2013 -0700 12.3 @@ -796,6 +796,56 @@ 12.4 VMError* volatile VMError::first_error = NULL; 12.5 volatile jlong VMError::first_error_tid = -1; 12.6 12.7 +/** Expand a pattern into a buffer starting at pos and open a file using constructed path */ 12.8 +static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) { 12.9 + int fd = -1; 12.10 + if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) { 12.11 + fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666); 12.12 + } 12.13 + return fd; 12.14 +} 12.15 + 12.16 +/** 12.17 + * Construct file name for a log file and return it's file descriptor. 12.18 + * Name and location depends on pattern, default_pattern params and access 12.19 + * permissions. 12.20 + */ 12.21 +static int prepare_log_file(const char* pattern, const char* default_pattern, char* buf, size_t buflen) { 12.22 + int fd = -1; 12.23 + 12.24 + // If possible, use specified pattern to construct log file name 12.25 + if (pattern != NULL) { 12.26 + fd = expand_and_open(pattern, buf, buflen, 0); 12.27 + } 12.28 + 12.29 + // Either user didn't specify, or the user's location failed, 12.30 + // so use the default name in the current directory 12.31 + if (fd == -1) { 12.32 + const char* cwd = os::get_current_directory(buf, buflen); 12.33 + if (cwd != NULL) { 12.34 + size_t pos = strlen(cwd); 12.35 + int fsep_len = jio_snprintf(&buf[pos], buflen-pos, "%s", os::file_separator()); 12.36 + pos += fsep_len; 12.37 + if (fsep_len > 0) { 12.38 + fd = expand_and_open(default_pattern, buf, buflen, pos); 12.39 + } 12.40 + } 12.41 + } 12.42 + 12.43 + // try temp directory if it exists. 12.44 + if (fd == -1) { 12.45 + const char* tmpdir = os::get_temp_directory(); 12.46 + if (tmpdir != NULL && strlen(tmpdir) > 0) { 12.47 + int pos = jio_snprintf(buf, buflen, "%s%s", tmpdir, os::file_separator()); 12.48 + if (pos > 0) { 12.49 + fd = expand_and_open(default_pattern, buf, buflen, pos); 12.50 + } 12.51 + } 12.52 + } 12.53 + 12.54 + return fd; 12.55 +} 12.56 + 12.57 void VMError::report_and_die() { 12.58 // Don't allocate large buffer on stack 12.59 static char buffer[O_BUFLEN]; 12.60 @@ -905,36 +955,7 @@ 12.61 // see if log file is already open 12.62 if (!log.is_open()) { 12.63 // open log file 12.64 - int fd = -1; 12.65 - 12.66 - if (ErrorFile != NULL) { 12.67 - bool copy_ok = 12.68 - Arguments::copy_expand_pid(ErrorFile, strlen(ErrorFile), buffer, sizeof(buffer)); 12.69 - if (copy_ok) { 12.70 - fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); 12.71 - } 12.72 - } 12.73 - 12.74 - if (fd == -1) { 12.75 - const char *cwd = os::get_current_directory(buffer, sizeof(buffer)); 12.76 - size_t len = strlen(cwd); 12.77 - // either user didn't specify, or the user's location failed, 12.78 - // so use the default name in the current directory 12.79 - jio_snprintf(&buffer[len], sizeof(buffer)-len, "%shs_err_pid%u.log", 12.80 - os::file_separator(), os::current_process_id()); 12.81 - fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); 12.82 - } 12.83 - 12.84 - if (fd == -1) { 12.85 - const char * tmpdir = os::get_temp_directory(); 12.86 - // try temp directory if it exists. 12.87 - if (tmpdir != NULL && tmpdir[0] != '\0') { 12.88 - jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log", 12.89 - tmpdir, os::file_separator(), os::current_process_id()); 12.90 - fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); 12.91 - } 12.92 - } 12.93 - 12.94 + int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer)); 12.95 if (fd != -1) { 12.96 out.print_raw("# An error report file with more information is saved as:\n# "); 12.97 out.print_raw_cr(buffer); 12.98 @@ -958,7 +979,7 @@ 12.99 // Run error reporting to determine whether or not to report the crash. 12.100 if (!transmit_report_done && should_report_bug(first_error->_id)) { 12.101 transmit_report_done = true; 12.102 - FILE* hs_err = ::fdopen(log.fd(), "r"); 12.103 + FILE* hs_err = os::open(log.fd(), "r"); 12.104 if (NULL != hs_err) { 12.105 ErrorReporter er; 12.106 er.call(hs_err, buffer, O_BUFLEN); 12.107 @@ -1008,7 +1029,19 @@ 12.108 skip_replay = true; 12.109 ciEnv* env = ciEnv::current(); 12.110 if (env != NULL) { 12.111 - env->dump_replay_data(); 12.112 + int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", buffer, sizeof(buffer)); 12.113 + if (fd != -1) { 12.114 + FILE* replay_data_file = os::open(fd, "w"); 12.115 + if (replay_data_file != NULL) { 12.116 + fileStream replay_data_stream(replay_data_file, /*need_close=*/true); 12.117 + env->dump_replay_data(&replay_data_stream); 12.118 + out.print_raw("#\n# Compiler replay data is saved as:\n# "); 12.119 + out.print_raw_cr(buffer); 12.120 + } else { 12.121 + out.print_raw("#\n# Can't open file to dump replay data. Error: "); 12.122 + out.print_raw_cr(strerror(os::get_last_error())); 12.123 + } 12.124 + } 12.125 } 12.126 } 12.127