8338883: Show warning when CreateCoredumpOnCrash set, but core dump will not happen
Reviewed-by: dholmes, jsjolen
This commit is contained in:
parent
7625b29920
commit
c34fb2c989
@ -104,49 +104,44 @@ static int clock_tics_per_sec = 100;
|
||||
size_t os::_os_min_stack_allowed = PTHREAD_STACK_MIN;
|
||||
|
||||
// Check core dump limit and report possible place where core can be found
|
||||
void os::check_dump_limit(char* buffer, size_t bufferSize) {
|
||||
void os::check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool check_only) {
|
||||
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
||||
jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
|
||||
VMError::record_coredump_status(buffer, false);
|
||||
return;
|
||||
}
|
||||
|
||||
int n;
|
||||
struct rlimit rlim;
|
||||
bool success;
|
||||
|
||||
char core_path[PATH_MAX];
|
||||
n = get_core_path(core_path, PATH_MAX);
|
||||
|
||||
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, 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 " UINT64_FORMAT " k). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", core_path, uint64_t(rlim.rlim_cur) / K);
|
||||
success = true;
|
||||
break;
|
||||
struct rlimit rlim;
|
||||
bool success = true;
|
||||
bool warn = true;
|
||||
char core_path[PATH_MAX];
|
||||
if (get_core_path(core_path, PATH_MAX) <= 0) {
|
||||
jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id());
|
||||
#ifdef LINUX
|
||||
} else if (core_path[0] == '"') { // redirect to user process
|
||||
jio_snprintf(buffer, bufferSize, "Core dumps may be processed with %s", core_path);
|
||||
#endif
|
||||
} else if (getrlimit(RLIMIT_CORE, &rlim) != 0) {
|
||||
jio_snprintf(buffer, bufferSize, "%s (may not exist)", core_path);
|
||||
} else {
|
||||
switch(rlim.rlim_cur) {
|
||||
case RLIM_INFINITY:
|
||||
jio_snprintf(buffer, bufferSize, "%s", core_path);
|
||||
warn = false;
|
||||
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 " UINT64_FORMAT " k). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", core_path, uint64_t(rlim.rlim_cur) / K);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!check_only) {
|
||||
VMError::record_coredump_status(buffer, success);
|
||||
} else if (warn) {
|
||||
warning("CreateCoredumpOnCrash specified, but %s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
VMError::record_coredump_status(buffer, success);
|
||||
}
|
||||
|
||||
bool os::committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size) {
|
||||
|
@ -1287,38 +1287,50 @@ void os::shutdown() {
|
||||
|
||||
static HANDLE dumpFile = nullptr;
|
||||
|
||||
// Check if dump file can be created.
|
||||
void os::check_dump_limit(char* buffer, size_t buffsz) {
|
||||
bool status = true;
|
||||
// Check if core dump is active and if a core dump file can be created
|
||||
void os::check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool check_only) {
|
||||
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
||||
jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
|
||||
status = false;
|
||||
}
|
||||
|
||||
jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
|
||||
VMError::record_coredump_status(buffer, false);
|
||||
} else {
|
||||
bool success = true;
|
||||
bool warn = true;
|
||||
#ifndef ASSERT
|
||||
if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
|
||||
jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");
|
||||
status = false;
|
||||
}
|
||||
if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
|
||||
jio_snprintf(buffer, bufferSize, "Minidumps are not enabled by default on client versions of Windows");
|
||||
success = false;
|
||||
warn = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status) {
|
||||
const char* cwd = get_current_directory(nullptr, 0);
|
||||
int pid = current_process_id();
|
||||
if (cwd != nullptr) {
|
||||
jio_snprintf(buffer, buffsz, "%s\\hs_err_pid%u.mdmp", cwd, pid);
|
||||
} else {
|
||||
jio_snprintf(buffer, buffsz, ".\\hs_err_pid%u.mdmp", pid);
|
||||
if (success) {
|
||||
if (!check_only) {
|
||||
const char* cwd = get_current_directory(nullptr, 0);
|
||||
int pid = current_process_id();
|
||||
if (cwd != nullptr) {
|
||||
jio_snprintf(buffer, bufferSize, "%s\\hs_err_pid%u.mdmp", cwd, pid);
|
||||
} else {
|
||||
jio_snprintf(buffer, bufferSize, ".\\hs_err_pid%u.mdmp", pid);
|
||||
}
|
||||
|
||||
if (dumpFile == nullptr &&
|
||||
(dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr))
|
||||
== INVALID_HANDLE_VALUE) {
|
||||
jio_snprintf(buffer, bufferSize, "Failed to create minidump file (0x%x).", GetLastError());
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
// For now on Windows, there are no more checks that we can do
|
||||
warn = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dumpFile == nullptr &&
|
||||
(dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr))
|
||||
== INVALID_HANDLE_VALUE) {
|
||||
jio_snprintf(buffer, buffsz, "Failed to create minidump file (0x%x).", GetLastError());
|
||||
status = false;
|
||||
if (!check_only) {
|
||||
VMError::record_coredump_status(buffer, success);
|
||||
} else if (warn) {
|
||||
warning("CreateCoredumpOnCrash specified, but %s", buffer);
|
||||
}
|
||||
}
|
||||
VMError::record_coredump_status(buffer, status);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, const void* context) {
|
||||
|
@ -939,7 +939,7 @@ class os: AllStatic {
|
||||
// provided buffer as a scratch buffer. The status message which will be written
|
||||
// into the error log either is file location or a short error message, depending
|
||||
// on the checking result.
|
||||
static void check_dump_limit(char* buffer, size_t bufferSize);
|
||||
static void check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool check_only = false);
|
||||
|
||||
// Get the default path to the core file
|
||||
// Returns the length of the string
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/flags/jvmFlagLimit.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
@ -665,6 +666,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
|
||||
log_info(os)("Initialized VM with process ID %d", os::current_process_id());
|
||||
|
||||
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && CreateCoredumpOnCrash) {
|
||||
char buffer[2*JVM_MAXPATHLEN];
|
||||
os::check_core_dump_prerequisites(buffer, sizeof(buffer), true);
|
||||
}
|
||||
|
||||
// Signal Dispatcher needs to be started before VMInit event is posted
|
||||
os::initialize_jdk_signal_support(CHECK_JNI_ERR);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2023, Red Hat, Inc. and/or its affiliates.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -1696,7 +1696,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt
|
||||
ShowMessageBoxOnError = false;
|
||||
}
|
||||
|
||||
os::check_dump_limit(buffer, sizeof(buffer));
|
||||
os::check_core_dump_prerequisites(buffer, sizeof(buffer));
|
||||
|
||||
// reset signal handlers or exception filter; make sure recursive crashes
|
||||
// are handled properly.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,6 +29,7 @@
|
||||
* java.management
|
||||
* jdk.internal.jvmstat/sun.jvmstat.monitor
|
||||
* @run driver CreateCoredumpOnCrash
|
||||
* @requires vm.flagless
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
@ -43,24 +44,61 @@ public class CreateCoredumpOnCrash {
|
||||
}
|
||||
}
|
||||
|
||||
private static String ulimitString(int limit) {
|
||||
String string = "ulimit -c ";
|
||||
if (limit != Integer.MAX_VALUE) {
|
||||
string += limit;
|
||||
} else {
|
||||
string += "unlimited";
|
||||
}
|
||||
return string+";";
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
runTest("-XX:-CreateCoredumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
||||
.shouldNotHaveExitValue(0);
|
||||
.shouldNotHaveExitValue(0);
|
||||
|
||||
if (Platform.isWindows()) {
|
||||
// The old CreateMinidumpOnCrash option should still work
|
||||
runTest("-XX:-CreateMinidumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
||||
.shouldNotHaveExitValue(0);
|
||||
.shouldNotHaveExitValue(0);
|
||||
} else {
|
||||
runTest("-XX:+CreateCoredumpOnCrash").shouldNotContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
||||
.shouldNotHaveExitValue(0);
|
||||
}
|
||||
String exec_cmd[] = {"sh", "-c", "ulimit -c"};
|
||||
OutputAnalyzer oa = new OutputAnalyzer(Runtime.getRuntime().exec(exec_cmd));
|
||||
oa.shouldHaveExitValue(0);
|
||||
if (!oa.contains("0\n")) {
|
||||
oa = runTest("-XX:+CreateCoredumpOnCrash");
|
||||
oa.shouldContain("Core dump will be written.");
|
||||
oa.shouldNotHaveExitValue(0);
|
||||
|
||||
oa = runTest("-XX:+CreateCoredumpOnCrash", ulimitString(1024));
|
||||
oa.shouldContain("warning: CreateCoredumpOnCrash specified, but");
|
||||
oa.shouldNotHaveExitValue(0);
|
||||
|
||||
oa = runTest("-XX:+CreateCoredumpOnCrash", ulimitString(0));
|
||||
oa.shouldContain("warning: CreateCoredumpOnCrash specified, but");
|
||||
oa.shouldNotHaveExitValue(0);
|
||||
} else {
|
||||
throw new Exception("ulimit is not set correctly, try 'ulimit -c unlimited' and re-run.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static OutputAnalyzer runTest(String option) throws Exception {
|
||||
return new OutputAnalyzer(
|
||||
ProcessTools.createLimitedTestJavaProcessBuilder(
|
||||
"-Xmx128m", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", option, Crasher.class.getName())
|
||||
.start());
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xmx128m",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
option, Crasher.class.getName());
|
||||
return new OutputAnalyzer(pb.start());
|
||||
}
|
||||
public static OutputAnalyzer runTest(String option, String limit) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xmx128m",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
option, new String("'"+Crasher.class.getName()+"'"));
|
||||
String args = "";
|
||||
for (String s:pb.command()) {
|
||||
args += s+" ";
|
||||
}
|
||||
String exec_cmd[] = {"sh", "-c", limit+args};
|
||||
return new OutputAnalyzer(Runtime.getRuntime().exec(exec_cmd));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user