--- old/src/os/aix/vm/os_aix.cpp 2014-10-15 22:48:56.033729678 +0900 +++ new/src/os/aix/vm/os_aix.cpp 2014-10-15 22:48:55.841731233 +0900 @@ -5088,6 +5088,8 @@ return 0; } + jio_snprintf(buffer, bufferSize, "%s/core or core.%d", current_process_id()); + return strlen(buffer); } --- old/src/os/bsd/vm/os_bsd.cpp 2014-10-15 22:48:56.776723663 +0900 +++ new/src/os/bsd/vm/os_bsd.cpp 2014-10-15 22:48:56.616724958 +0900 @@ -4689,7 +4689,7 @@ // Get the default path to the core file // Returns the length of the string int os::get_core_path(char* buffer, size_t bufferSize) { - int n = jio_snprintf(buffer, bufferSize, "/cores"); + int n = jio_snprintf(buffer, bufferSize, "/cores/core or core.%d", current_process_id()); // Truncate if theoretical string was longer than bufferSize n = MIN2(n, (int)bufferSize); --- old/src/os/linux/vm/os_linux.cpp 2014-10-15 22:48:57.520717639 +0900 +++ new/src/os/linux/vm/os_linux.cpp 2014-10-15 22:48:57.374718821 +0900 @@ -103,6 +103,7 @@ # include # include # include +# include PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC @@ -5997,13 +5998,150 @@ // 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') { + jio_snprintf(&core_path[n], PATH_MAX - n, ".%d", current_process_id()); + } + + } + + if (core_path[0] == '/') { + jio_snprintf(buffer, bufferSize, 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[1], p, current_process_id()); + } else { + jio_snprintf(buffer, bufferSize, "%s/%s", p, core_path); + } + + } + return strlen(buffer); } --- old/src/os/posix/vm/os_posix.cpp 2014-10-15 22:48:58.312711227 +0900 +++ new/src/os/posix/vm/os_posix.cpp 2014-10-15 22:48:58.131712693 +0900 @@ -50,16 +50,25 @@ int n; struct rlimit rlim; bool success; + char core_path[PATH_MAX]; - n = get_core_path(buffer, bufferSize); + n = get_core_path(core_path, PATH_MAX); - if (getrlimit(RLIMIT_CORE, &rlim) != 0) { - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id()); + if (n <= 0) { + jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id()); + success = true; +#ifdef LINUX + } else if (core_path[0] == '"') { // redirect to user process + jio_snprintf(buffer, bufferSize, "Core dumps may be processed with %s", core_path); + success = true; +#endif + } else if (getrlimit(RLIMIT_CORE, &rlim) != 0) { + jio_snprintf(buffer, bufferSize, "%s (may not exist)", core_path); success = true; } else { switch(rlim.rlim_cur) { case RLIM_INFINITY: - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id()); + jio_snprintf(buffer, bufferSize, "%s", core_path); success = true; break; case 0: @@ -67,7 +76,7 @@ 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)); + 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; } --- old/src/os/solaris/vm/os_solaris.cpp 2014-10-15 22:48:58.840706953 +0900 +++ new/src/os/solaris/vm/os_solaris.cpp 2014-10-15 22:48:58.697708110 +0900 @@ -6045,6 +6045,8 @@ return 0; } + jio_snprintf(buffer, bufferSize, "%s/core or core.%d", current_process_id()); + return strlen(buffer); }