8074354: Make CreateMinidumpOnCrash a new name and available on all platforms

Rename CreateMinidumpOnCrash which is used only for Windows as CreateCoredumpOnCrash and make it available for all platforms. Changed order for dumping core on Windows to be similar on other platforms. Also reviewed by thomas.stuefe@gmail.com

Co-authored-by: Thomas Stuefe <thomas.stuefe@gmail.com>
Reviewed-by: dcubed
This commit is contained in:
Yumin Qi 2015-04-15 17:34:28 -07:00
parent 47d774ab34
commit d30de5ab31
20 changed files with 141 additions and 90 deletions

View File

@ -1211,6 +1211,10 @@ void os::shutdown() {
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core) {
abort(dump_core, NULL, NULL);
}
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT

View File

@ -1132,6 +1132,10 @@ void os::shutdown() {
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core) {
abort(dump_core, NULL, NULL);
}
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT

View File

@ -1473,6 +1473,10 @@ void os::shutdown() {
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core) {
abort(dump_core, NULL, NULL);
}
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
@ -46,7 +46,7 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#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) {
void os::check_dump_limit(char* buffer, size_t bufferSize) {
int n;
struct rlimit rlim;
bool success;
@ -82,7 +82,7 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
}
}
VMError::report_coredump_status(buffer, success);
VMError::record_coredump_status(buffer, success);
}
int os::get_native_stack(address* stack, int frames, int toSkip) {

View File

@ -1521,6 +1521,10 @@ void os::shutdown() {
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core) {
abort(dump_core, NULL, NULL);
}
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT

View File

@ -987,7 +987,34 @@ static BOOL (WINAPI *_MiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
PMINIDUMP_USER_STREAM_INFORMATION,
PMINIDUMP_CALLBACK_INFORMATION);
void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) {
static HANDLE dumpFile = NULL;
// Check if dump file can be created.
void os::check_dump_limit(char* buffer, size_t buffsz) {
bool status = true;
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
status = false;
} else {
const char* cwd = get_current_directory(NULL, 0);
int pid = current_process_id();
if (cwd != NULL) {
jio_snprintf(buffer, buffsz, "%s\\hs_err_pid%u.mdmp", cwd, pid);
} else {
jio_snprintf(buffer, buffsz, ".\\hs_err_pid%u.mdmp", pid);
}
if (dumpFile == NULL &&
(dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
== INVALID_HANDLE_VALUE) {
jio_snprintf(buffer, buffsz, "Failed to create minidump file (0x%x).", GetLastError());
status = false;
}
}
VMError::record_coredump_status(buffer, status);
}
void os::abort(bool dump_core, void* siginfo, void* context) {
HINSTANCE dbghelp;
EXCEPTION_POINTERS ep;
MINIDUMP_EXCEPTION_INFORMATION mei;
@ -995,33 +1022,22 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
HANDLE hProcess = GetCurrentProcess();
DWORD processId = GetCurrentProcessId();
HANDLE dumpFile;
MINIDUMP_TYPE dumpType;
static const char* cwd;
// Default is to always create dump for debug builds, on product builds only dump on server versions of Windows.
#ifndef ASSERT
// If running on a client version of Windows and user has not explicitly enabled dumping
if (!os::win32::is_windows_server() && !CreateMinidumpOnCrash) {
VMError::report_coredump_status("Minidumps are not enabled by default on client versions of Windows", false);
return;
// If running on a server version of Windows and user has explictly disabled dumping
} else if (os::win32::is_windows_server() && !FLAG_IS_DEFAULT(CreateMinidumpOnCrash) && !CreateMinidumpOnCrash) {
VMError::report_coredump_status("Minidump has been disabled from the command line", false);
return;
shutdown();
if (!dump_core || dumpFile == NULL) {
if (dumpFile != NULL) {
CloseHandle(dumpFile);
}
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
#else
if (!FLAG_IS_DEFAULT(CreateMinidumpOnCrash) && !CreateMinidumpOnCrash) {
VMError::report_coredump_status("Minidump has been disabled from the command line", false);
return;
}
#endif
dbghelp = os::win32::load_Windows_dll("DBGHELP.DLL", NULL, 0);
if (dbghelp == NULL) {
VMError::report_coredump_status("Failed to load dbghelp.dll", false);
return;
jio_fprintf(stderr, "Failed to load dbghelp.dll\n");
CloseHandle(dumpFile);
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
_MiniDumpWriteDump =
@ -1033,30 +1049,23 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
"MiniDumpWriteDump"));
if (_MiniDumpWriteDump == NULL) {
VMError::report_coredump_status("Failed to find MiniDumpWriteDump() in module dbghelp.dll", false);
return;
jio_fprintf(stderr, "Failed to find MiniDumpWriteDump() in module dbghelp.dll.\n");
CloseHandle(dumpFile);
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData);
// Older versions of dbghelp.h doesn't contain all the dumptypes we want, dbghelp.h with
// API_VERSION_NUMBER 11 or higher contains the ones we want though
// Older versions of dbghelp.h do not contain all the dumptypes we want, dbghelp.h with
// API_VERSION_NUMBER 11 or higher contains the ones we want though
#if API_VERSION_NUMBER >= 11
dumpType = (MINIDUMP_TYPE)(dumpType | MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo |
MiniDumpWithUnloadedModules);
#endif
cwd = get_current_directory(NULL, 0);
jio_snprintf(buffer, bufferSize, "%s\\hs_err_pid%u.mdmp", cwd, current_process_id());
dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (dumpFile == INVALID_HANDLE_VALUE) {
VMError::report_coredump_status("Failed to create file for dumping", false);
return;
}
if (exceptionRecord != NULL && contextRecord != NULL) {
ep.ContextRecord = (PCONTEXT) contextRecord;
ep.ExceptionRecord = (PEXCEPTION_RECORD) exceptionRecord;
if (siginfo != NULL && context != NULL) {
ep.ContextRecord = (PCONTEXT) context;
ep.ExceptionRecord = (PEXCEPTION_RECORD) siginfo;
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = &ep;
@ -1065,38 +1074,18 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
pmei = NULL;
}
// Older versions of dbghelp.dll (the one shipped with Win2003 for example) may not support all
// the dump types we really want. If first call fails, lets fall back to just use MiniDumpWithFullMemory then.
if (_MiniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) == false &&
_MiniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL) == false) {
DWORD error = GetLastError();
LPTSTR msgbuf = NULL;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, 0, (LPTSTR)&msgbuf, 0, NULL) != 0) {
jio_snprintf(buffer, bufferSize, "Call to MiniDumpWriteDump() failed (Error 0x%x: %s)", error, msgbuf);
LocalFree(msgbuf);
} else {
// Call to FormatMessage failed, just include the result from GetLastError
jio_snprintf(buffer, bufferSize, "Call to MiniDumpWriteDump() failed (Error 0x%x)", error);
}
VMError::report_coredump_status(buffer, false);
} else {
VMError::report_coredump_status(buffer, true);
jio_fprintf(stderr, "Call to MiniDumpWriteDump() failed (Error 0x%x)\n", GetLastError());
}
CloseHandle(dumpFile);
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
void os::abort(bool dump_core) {
os::shutdown();
// no core dump on Windows
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
abort(dump_core, NULL, NULL);
}
// Die immediately, no exit hook, no abort hook, no cleanup.

View File

@ -3241,6 +3241,15 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
"ManagementServer is not supported in this VM.\n");
return JNI_ERR;
#endif // INCLUDE_MANAGEMENT
// CreateMinidumpOnCrash is removed, and replaced by CreateCoredumpOnCrash
} else if (match_option(option, "-XX:+CreateMinidumpOnCrash")) {
FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, true);
jio_fprintf(defaultStream::output_stream(),
"CreateMinidumpOnCrash is replaced by CreateCoredumpOnCrash: CreateCoredumpOnCrash is on\n");
} else if (match_option(option, "-XX:-CreateMinidumpOnCrash")) {
FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, false);
jio_fprintf(defaultStream::output_stream(),
"CreateMinidumpOnCrash is replaced by CreateCoredumpOnCrash: CreateCoredumpOnCrash is off\n");
} else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
// Skip -XX:Flags= since that case has already been handled
if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) {

View File

@ -936,8 +936,8 @@ class CommandLineFlags {
product(bool, ShowMessageBoxOnError, false, \
"Keep process alive on VM fatal error") \
\
product(bool, CreateMinidumpOnCrash, false, \
"Create minidump on VM fatal error") \
product(bool, CreateCoredumpOnCrash, true, \
"Create core/mini dump on VM fatal error") \
\
product_pd(bool, UseOSErrorReporting, \
"Let VM fatal error propagate to the OS (ie. WER on Windows)") \

View File

@ -492,6 +492,7 @@ class os: AllStatic {
// Terminate with an error. Default is to generate a core file on platforms
// that support such things. This calls shutdown() and then aborts.
static void abort(bool dump_core, void *siginfo, void *context);
static void abort(bool dump_core = true);
// Die immediately, no exit hook, no abort hook, no cleanup.
@ -716,8 +717,13 @@ class os: AllStatic {
// Structured OS Exception support
static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
// On Windows this will create an actual minidump, on Linux/Solaris it will simply check core dump limits
static void check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize);
// On Posix compatible OS it will simply check core dump limits while on Windows
// it will check if dump file can be created. Check or prepare a core dump to be
// taken at a later point in the same thread in os::abort(). Use the caller
// 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);
// Get the default path to the core file
// Returns the length of the string

View File

@ -217,7 +217,7 @@ static void print_bug_submit_message(outputStream *out, Thread *thread) {
bool VMError::coredump_status;
char VMError::coredump_message[O_BUFLEN];
void VMError::report_coredump_status(const char* message, bool status) {
void VMError::record_coredump_status(const char* message, bool status) {
coredump_status = status;
strncpy(coredump_message, message, sizeof(coredump_message));
coredump_message[sizeof(coredump_message)-1] = 0;
@ -525,10 +525,14 @@ void VMError::report(outputStream* st) {
}
STEP(63, "(printing core file information)")
st->print("# ");
if (coredump_status) {
st->print("Core dump written. Default location: %s", coredump_message);
if (CreateCoredumpOnCrash) {
if (coredump_status) {
st->print("Core dump will be written. %s", coredump_message);
} else {
st->print("No core dump will be written. %s", coredump_message);
}
} else {
st->print("Failed to write core dump. %s", coredump_message);
st->print("CreateCoredumpOnCrash turned off, no core file dumped");
}
st->cr();
st->print_cr("#");
@ -918,7 +922,7 @@ void VMError::report_and_die() {
static bool transmit_report_done = false; // done error reporting
if (SuppressFatalErrorMessage) {
os::abort();
os::abort(CreateCoredumpOnCrash);
}
jlong mytid = os::current_thread_id();
if (first_error == NULL &&
@ -936,8 +940,7 @@ void VMError::report_and_die() {
ShowMessageBoxOnError = false;
}
// Write a minidump on Windows, check core dump limits on Linux/Solaris
os::check_or_create_dump(_siginfo, _context, buffer, sizeof(buffer));
os::check_dump_limit(buffer, sizeof(buffer));
// reset signal handlers or exception filter; make sure recursive crashes
// are handled properly.
@ -1108,7 +1111,7 @@ void VMError::report_and_die() {
if (!skip_os_abort) {
skip_os_abort = true;
bool dump_core = should_report_bug(first_error->_id);
os::abort(dump_core);
os::abort(dump_core && CreateCoredumpOnCrash, _siginfo, _context);
}
// if os::abort() doesn't abort, try os::die();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2015, 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
@ -117,8 +117,8 @@ public:
// return a string to describe the error
char *error_string(char* buf, int buflen);
// Report status of core/minidump
static void report_coredump_status(const char* message, bool status);
// Record status of core/minidump
static void record_coredump_status(const char* message, bool status);
// main error reporting function
void report_and_die();

View File

@ -48,7 +48,7 @@ public class ProblematicFrameTest {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-Xmx64m", "-XX:-TransmitErrorReport", "-XX:-CreateMinidumpOnCrash", Crasher.class.getName());
"-Xmx64m", "-XX:-TransmitErrorReport", "-XX:-CreateCoredumpOnCrash", Crasher.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldNotMatch("error occurred during error reporting \\(printing problematic frame\\)");
}

View File

@ -53,6 +53,7 @@ public class SafeFetchInErrorHandlingTest {
"-Xmx100M",
"-XX:ErrorHandlerTest=14",
"-XX:+TestSafeFetchInErrorHandler",
"-XX:-CreateCoredumpOnCrash",
"-version");
OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());

View File

@ -1,12 +1,26 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
/*
* Copyright (c) 2013, 2015, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.Platform;
import com.oracle.java.testlibrary.ProcessTools;
/*
* @test
@ -18,6 +32,16 @@ import com.oracle.java.testlibrary.ProcessTools;
* java.management
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.Platform;
import com.oracle.java.testlibrary.ProcessTools;
public class SecondaryErrorTest {
@ -35,6 +59,7 @@ public class SecondaryErrorTest {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-Xmx100M",
"-XX:-CreateCoredumpOnCrash",
"-XX:ErrorHandlerTest=15",
"-XX:TestCrashInErrorHandler=14",
"-version");

View File

@ -49,7 +49,7 @@ public class AssertSafepointCheckConsistency1 {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:-TransmitErrorReport",
"-XX:-CreateMinidumpOnCrash",
"-XX:-CreateCoredumpOnCrash",
"-Xmx32m",
"AssertSafepointCheckConsistency1",
"test");

View File

@ -49,7 +49,7 @@ public class AssertSafepointCheckConsistency2 {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:-TransmitErrorReport",
"-XX:-CreateMinidumpOnCrash",
"-XX:-CreateCoredumpOnCrash",
"-Xmx32m",
"AssertSafepointCheckConsistency2",
"test");

View File

@ -49,7 +49,7 @@ public class AssertSafepointCheckConsistency3 {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:-TransmitErrorReport",
"-XX:-CreateMinidumpOnCrash",
"-XX:-CreateCoredumpOnCrash",
"-Xmx32m",
"AssertSafepointCheckConsistency3",
"test");

View File

@ -49,7 +49,7 @@ public class AssertSafepointCheckConsistency4 {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:-TransmitErrorReport",
"-XX:-CreateMinidumpOnCrash",
"-XX:-CreateCoredumpOnCrash",
"-Xmx32m",
"AssertSafepointCheckConsistency4",
"test");

View File

@ -45,6 +45,7 @@ public class RangeCheck {
true,
"-Xmx32m",
"-XX:-TransmitErrorReport",
"-XX:-CreateCoredumpOnCrash",
"-XX:-InlineUnsafeOps", // The compiler intrinsics doesn't have the assert
DummyClassWithMainRangeCheck.class.getName());

View File

@ -50,6 +50,7 @@ public class ReadFromNoaccessArea {
"-XX:+WhiteBoxAPI",
"-XX:+UseCompressedOops",
"-XX:HeapBaseMinAddress=33G",
"-XX:-CreateCoredumpOnCrash",
"-Xmx32m",
DummyClassWithMainTryingToReadFromNoaccessArea.class.getName());