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;
|
size_t os::_os_min_stack_allowed = PTHREAD_STACK_MIN;
|
||||||
|
|
||||||
// Check core dump limit and report possible place where core can be found
|
// 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) {
|
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
||||||
jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
|
jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
|
||||||
VMError::record_coredump_status(buffer, false);
|
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 {
|
} else {
|
||||||
switch(rlim.rlim_cur) {
|
struct rlimit rlim;
|
||||||
case RLIM_INFINITY:
|
bool success = true;
|
||||||
jio_snprintf(buffer, bufferSize, "%s", core_path);
|
bool warn = true;
|
||||||
success = true;
|
char core_path[PATH_MAX];
|
||||||
break;
|
if (get_core_path(core_path, PATH_MAX) <= 0) {
|
||||||
case 0:
|
jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id());
|
||||||
jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again");
|
#ifdef LINUX
|
||||||
success = false;
|
} else if (core_path[0] == '"') { // redirect to user process
|
||||||
break;
|
jio_snprintf(buffer, bufferSize, "Core dumps may be processed with %s", core_path);
|
||||||
default:
|
#endif
|
||||||
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);
|
} else if (getrlimit(RLIMIT_CORE, &rlim) != 0) {
|
||||||
success = true;
|
jio_snprintf(buffer, bufferSize, "%s (may not exist)", core_path);
|
||||||
break;
|
} 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) {
|
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;
|
static HANDLE dumpFile = nullptr;
|
||||||
|
|
||||||
// Check if dump file can be created.
|
// Check if core dump is active and if a core dump file can be created
|
||||||
void os::check_dump_limit(char* buffer, size_t buffsz) {
|
void os::check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool check_only) {
|
||||||
bool status = true;
|
|
||||||
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
||||||
jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
|
jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
|
||||||
status = false;
|
VMError::record_coredump_status(buffer, false);
|
||||||
}
|
} else {
|
||||||
|
bool success = true;
|
||||||
|
bool warn = true;
|
||||||
#ifndef ASSERT
|
#ifndef ASSERT
|
||||||
if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
|
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");
|
jio_snprintf(buffer, bufferSize, "Minidumps are not enabled by default on client versions of Windows");
|
||||||
status = false;
|
success = false;
|
||||||
}
|
warn = true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (status) {
|
if (success) {
|
||||||
const char* cwd = get_current_directory(nullptr, 0);
|
if (!check_only) {
|
||||||
int pid = current_process_id();
|
const char* cwd = get_current_directory(nullptr, 0);
|
||||||
if (cwd != nullptr) {
|
int pid = current_process_id();
|
||||||
jio_snprintf(buffer, buffsz, "%s\\hs_err_pid%u.mdmp", cwd, pid);
|
if (cwd != nullptr) {
|
||||||
} else {
|
jio_snprintf(buffer, bufferSize, "%s\\hs_err_pid%u.mdmp", cwd, pid);
|
||||||
jio_snprintf(buffer, buffsz, ".\\hs_err_pid%u.mdmp", 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 &&
|
if (!check_only) {
|
||||||
(dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr))
|
VMError::record_coredump_status(buffer, success);
|
||||||
== INVALID_HANDLE_VALUE) {
|
} else if (warn) {
|
||||||
jio_snprintf(buffer, buffsz, "Failed to create minidump file (0x%x).", GetLastError());
|
warning("CreateCoredumpOnCrash specified, but %s", buffer);
|
||||||
status = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VMError::record_coredump_status(buffer, status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void os::abort(bool dump_core, void* siginfo, const void* context) {
|
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
|
// 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
|
// into the error log either is file location or a short error message, depending
|
||||||
// on the checking result.
|
// 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
|
// Get the default path to the core file
|
||||||
// Returns the length of the string
|
// Returns the length of the string
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#include "runtime/fieldDescriptor.inline.hpp"
|
#include "runtime/fieldDescriptor.inline.hpp"
|
||||||
#include "runtime/flags/jvmFlagLimit.hpp"
|
#include "runtime/flags/jvmFlagLimit.hpp"
|
||||||
#include "runtime/globals.hpp"
|
#include "runtime/globals.hpp"
|
||||||
|
#include "runtime/globals_extension.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/interfaceSupport.inline.hpp"
|
#include "runtime/interfaceSupport.inline.hpp"
|
||||||
#include "runtime/java.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());
|
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
|
// Signal Dispatcher needs to be started before VMInit event is posted
|
||||||
os::initialize_jdk_signal_support(CHECK_JNI_ERR);
|
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) 2017, 2020 SAP SE. All rights reserved.
|
||||||
* Copyright (c) 2023, Red Hat, Inc. and/or its affiliates.
|
* Copyright (c) 2023, Red Hat, Inc. and/or its affiliates.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* 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;
|
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
|
// reset signal handlers or exception filter; make sure recursive crashes
|
||||||
// are handled properly.
|
// 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -29,6 +29,7 @@
|
|||||||
* java.management
|
* java.management
|
||||||
* jdk.internal.jvmstat/sun.jvmstat.monitor
|
* jdk.internal.jvmstat/sun.jvmstat.monitor
|
||||||
* @run driver CreateCoredumpOnCrash
|
* @run driver CreateCoredumpOnCrash
|
||||||
|
* @requires vm.flagless
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import jdk.test.lib.process.ProcessTools;
|
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 {
|
public static void main(String[] args) throws Exception {
|
||||||
runTest("-XX:-CreateCoredumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
runTest("-XX:-CreateCoredumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
||||||
.shouldNotHaveExitValue(0);
|
.shouldNotHaveExitValue(0);
|
||||||
|
|
||||||
if (Platform.isWindows()) {
|
if (Platform.isWindows()) {
|
||||||
// The old CreateMinidumpOnCrash option should still work
|
// The old CreateMinidumpOnCrash option should still work
|
||||||
runTest("-XX:-CreateMinidumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
runTest("-XX:-CreateMinidumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
||||||
.shouldNotHaveExitValue(0);
|
.shouldNotHaveExitValue(0);
|
||||||
} else {
|
} else {
|
||||||
runTest("-XX:+CreateCoredumpOnCrash").shouldNotContain("CreateCoredumpOnCrash turned off, no core file dumped")
|
String exec_cmd[] = {"sh", "-c", "ulimit -c"};
|
||||||
.shouldNotHaveExitValue(0);
|
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 {
|
public static OutputAnalyzer runTest(String option) throws Exception {
|
||||||
return new OutputAnalyzer(
|
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xmx128m",
|
||||||
ProcessTools.createLimitedTestJavaProcessBuilder(
|
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||||
"-Xmx128m", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", option, Crasher.class.getName())
|
option, Crasher.class.getName());
|
||||||
.start());
|
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