--- old/src/os/aix/vm/os_aix.cpp 2014-10-14 18:23:57.503835122 +0900 +++ new/src/os/aix/vm/os_aix.cpp 2014-10-14 18:23:57.368836086 +0900 @@ -5091,6 +5091,36 @@ return strlen(buffer); } +// Check core dump limit and report possible place where core can be found +void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { + int n; + struct rlimit rlim; + bool success; + + n = get_core_path(buffer, bufferSize); + + if (getrlimit(RLIMIT_CORE, &rlim) != 0) { + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id()); + success = true; + } else { + switch(rlim.rlim_cur) { + case RLIM_INFINITY: + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id()); + success = true; + break; +e 0: + jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again"); + success = false; + break; + default: + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", current_process_id(), (unsigned long)(rlim.rlim_cur >> 10)); + success = true; + break; + } + } + VMError::report_coredump_status(buffer, success); +} + #ifndef PRODUCT void TestReserveMemorySpecial_test() { // No tests available for this platform --- old/src/os/bsd/vm/os_bsd.cpp 2014-10-14 18:23:58.288829515 +0900 +++ new/src/os/bsd/vm/os_bsd.cpp 2014-10-14 18:23:58.153830479 +0900 @@ -4697,6 +4697,36 @@ return n; } +// Check core dump limit and report possible place where core can be found +void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { + int n; + struct rlimit rlim; + bool success; + + n = get_core_path(buffer, bufferSize); + + if (getrlimit(RLIMIT_CORE, &rlim) != 0) { + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id()); + success = true; + } else { + switch(rlim.rlim_cur) { + case RLIM_INFINITY: + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id()); + success = true; + break; + case 0: + jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again"); + success = false; + break; + default: + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", current_process_id(), (unsigned long)(rlim.rlim_cur >> 10)); + success = true; + break; + } + } + VMError::report_coredump_status(buffer, success); +} + #ifndef PRODUCT void TestReserveMemorySpecial_test() { // No tests available for this platform --- old/src/os/linux/vm/os_linux.cpp 2014-10-14 18:23:58.922824986 +0900 +++ new/src/os/linux/vm/os_linux.cpp 2014-10-14 18:23:58.785825964 +0900 @@ -103,6 +103,7 @@ # include # include # include +# include PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC @@ -5997,16 +5998,194 @@ // Get the default path to the core file // Returns the length of the string int os::get_core_path(char* buffer, size_t bufferSize) { - const char* p = get_current_directory(buffer, bufferSize); + /* + * Max length of /proc/sys/kernel/core_pattern is 128 characters. + * See https://www.kernel.org/doc/Documentation/sysctl/kernel.txt + */ + const int core_pattern_len = 129; + char core_pattern[core_pattern_len] = {0}; - if (p == NULL) { - assert(p != NULL, "failed to get current directory"); + FILE *core_pattern_file = fopen("/proc/sys/kernel/core_pattern", "r"); + if (core_pattern_file != NULL) { + char *ret_ptr = fgets(core_pattern, core_pattern_len, core_pattern_file); + fclose(core_pattern_file); + + if (ret_ptr != NULL) { + char *last_char = core_pattern + strlen(core_pattern) - 1; + if (*last_char == '\n') { + *last_char = '\0'; + } + } + + } + + if (strlen(core_pattern) == 0) { return 0; } + // Get executable path for 'e' and 'E' + char exe_path[PATH_MAX] = {0}; + readlink("/proc/self/exe", exe_path, PATH_MAX); + + char core_path[PATH_MAX] = {0}; + bool with_pid = false; + size_t n = 0; + char *core_pattern_seq = core_pattern; + while (*core_pattern_seq) { + + if (*core_pattern_seq == '%') { + int written = 0; + core_pattern_seq++; // Get format character + + switch (*core_pattern_seq) { + + case '\0': // NULL termination + break; + + case '%': // double percent + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%%"); + break; + + case 'p': // pid + with_pid = true; + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%d", current_process_id()); + break; + + case 'u': // uid + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%d", getuid()); + break; + + case 'g': // gid + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%d", getgid()); + break; + + case 'd': // dump mode + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%d", + prctl(PR_GET_DUMPABLE, NULL, NULL, NULL, NULL)); + break; + + case 'h': // hostname + struct utsname un; + uname(&un); // This call will be succeeded. + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%s", un.nodename); + break; + + case 'e': // executable filename (shorten) + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%s", basename(exe_path)); + break; + + case 'E': // executable filename (path) + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%s", exe_path); + break; + + case 'c': // core limit size + struct rlimit rlim; + getrlimit(RLIMIT_CORE, &rlim); // Calling getrlimit() to myself will be succeeded. + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%lu", rlim.rlim_cur); + break; + + /* + * We cannot other values. + * e.g. 'P' (global pid), 's' (signal), 't' (UNIX time of dump) + * + * - 't' will set to core dump time in Linux kernel. + * Thus we cannot set it in this function. + * - If user set undefined character, Linux kernel will drop it. + * We remain it because Linux kernel may define it in the future. + */ + default: + written = jio_snprintf(&core_path[n], PATH_MAX - n, "%%%c", *core_pattern_seq); + break; + + } + + n += written; + } else { + core_path[n] = *core_pattern_seq; + n++; + } + + core_pattern_seq++; // Get next character + } + + if (!with_pid && (core_path[0] != '|')) { + char val[2] = {0}; + FILE *core_uses_pid_file = fopen("/proc/sys/kernel/core_uses_pid", "r"); + if (core_uses_pid_file != NULL) { + fgets(val, 2, core_uses_pid_file); + fclose(core_uses_pid_file); + } + + if (val[0] == '1') { + n += jio_snprintf(&core_path[n], PATH_MAX - n, ".%d", current_process_id()); + } + + } + + if (n > bufferSize) { + n = bufferSize; + } + + if (core_path[0] == '/') { + jio_snprintf(buffer, n, core_path); + } else { + char cwd[PATH_MAX]; + const char* p = get_current_directory(cwd, PATH_MAX); + + if (p == NULL) { + assert(p != NULL, "failed to get current directory"); + return 0; + } + + if (core_path[0] == '|') { + jio_snprintf(buffer, bufferSize, "%s (or dumping to %s/core.%d)", + core_path, p, current_process_id()); + } else { + jio_snprintf(buffer, bufferSize, "%s/%s", p, core_path); + } + + } + return strlen(buffer); } +// Check core dump limit and report possible place where core can be found +void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { + int n; + bool success; + char core_path[PATH_MAX]; + + n = get_core_path(core_path, PATH_MAX); + + if (n == 0) { + jio_snprintf(buffer, bufferSize, "/core or core.%d (may not exist)", current_process_id()); + success = true; + } else if (core_path[0] == '|') { + jio_snprintf(buffer, bufferSize, "Core dumps may be processed with \"%s\"", &core_path[1]); + success = true; + } else { + struct rlimit rlim; + getrlimit(RLIMIT_CORE, &rlim); // Calling getrlimit() to myself will be succeeded. + + switch(rlim.rlim_cur) { + case RLIM_INFINITY: + jio_snprintf(buffer, bufferSize, "%s", core_path); + success = true; + break; + case 0: + jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again"); + success = false; + break; + default: + jio_snprintf(buffer, bufferSize, "%s (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", core_path, (unsigned long)(rlim.rlim_cur >> 10)); + success = true; + break; + } + } + VMError::report_coredump_status(buffer, success); +} + + #ifdef JAVASE_EMBEDDED // // A thread to watch the '/dev/mem_notify' device, which will tell us when the OS is running low on memory. --- old/src/os/posix/vm/os_posix.cpp 2014-10-14 18:23:59.662819700 +0900 +++ new/src/os/posix/vm/os_posix.cpp 2014-10-14 18:23:59.530820643 +0900 @@ -45,36 +45,6 @@ #endif #define IS_VALID_PID(p) (p > 0 && p < MAX_PID) -// Check core dump limit and report possible place where core can be found -void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { - int n; - struct rlimit rlim; - bool success; - - n = get_core_path(buffer, bufferSize); - - if (getrlimit(RLIMIT_CORE, &rlim) != 0) { - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id()); - success = true; - } else { - switch(rlim.rlim_cur) { - case RLIM_INFINITY: - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id()); - success = true; - break; - case 0: - jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again"); - success = false; - break; - default: - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", current_process_id(), (unsigned long)(rlim.rlim_cur >> 10)); - success = true; - break; - } - } - VMError::report_coredump_status(buffer, success); -} - int os::get_native_stack(address* stack, int frames, int toSkip) { #ifdef _NMT_NOINLINE_ toSkip++; --- old/src/os/solaris/vm/os_solaris.cpp 2014-10-14 18:24:00.203815836 +0900 +++ new/src/os/solaris/vm/os_solaris.cpp 2014-10-14 18:24:00.068816800 +0900 @@ -6048,6 +6048,36 @@ return strlen(buffer); } +// Check core dump limit and report possible place where core can be found +void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { + int n; + struct rlimit rlim; + bool success; + + n = get_core_path(buffer, bufferSize); + + if (getrlimit(RLIMIT_CORE, &rlim) != 0) { + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id()); + success = true; + } else { + switch(rlim.rlim_cur) { + case RLIM_INFINITY: + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id()); + success = true; + break; + case 0: + jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again"); + success = false; + break; + default: + jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", current_process_id(), (unsigned long)(rlim.rlim_cur >> 10)); + success = true; + break; + } + } + VMError::report_coredump_status(buffer, success); +} + #ifndef PRODUCT void TestReserveMemorySpecial_test() { // No tests available for this platform