Skip to content

Commit

Permalink
8310228: Improve error reporting for uncaught native exceptions on Wi…
Browse files Browse the repository at this point in the history
…ndows

Reviewed-by: stuefe
Backport-of: 38bf1192b637cf3513cb25ac21f513bfb51cb55b
  • Loading branch information
GoeLin committed May 7, 2024
1 parent 7a400f2 commit ed2f5a8
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 22 deletions.
2 changes: 2 additions & 0 deletions make/test/JtregNativeHotspot.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -1511,6 +1511,8 @@ else
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMonitorWithDeadObjectTest += -lpthread
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativeStack += -lpthread
BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exeGetCreatedJavaVMs := -ljvm -lpthread

BUILD_HOTSPOT_JTREG_EXCLUDE += libNativeException.c
endif

ifeq ($(ASAN_ENABLED), true)
Expand Down
57 changes: 35 additions & 22 deletions src/hotspot/os/windows/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,12 @@ void os::run_periodic_checks(outputStream* st) {
return;
}

#ifndef _WIN64
// previous UnhandledExceptionFilter, if there is one
static LPTOP_LEVEL_EXCEPTION_FILTER prev_uef_handler = nullptr;
#endif

LONG WINAPI Handle_FLT_Exception(struct _EXCEPTION_POINTERS* exceptionInfo);
static LONG WINAPI Uncaught_Exception_Handler(struct _EXCEPTION_POINTERS* exceptionInfo);

void os::init_system_properties_values() {
// sysclasspath, java_home, dll_dir
Expand Down Expand Up @@ -397,7 +399,7 @@ void os::init_system_properties_values() {

#ifndef _WIN64
// set our UnhandledExceptionFilter and save any previous one
prev_uef_handler = SetUnhandledExceptionFilter(Handle_FLT_Exception);
prev_uef_handler = SetUnhandledExceptionFilter(Uncaught_Exception_Handler);
#endif

// Done
Expand Down Expand Up @@ -2491,9 +2493,7 @@ LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) {

#if defined(_M_AMD64) || defined(_M_IX86)
//-----------------------------------------------------------------------------
LONG WINAPI Handle_FLT_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) {
PCONTEXT ctx = exceptionInfo->ContextRecord;
#ifndef _WIN64
static bool handle_FLT_exception(struct _EXCEPTION_POINTERS* exceptionInfo) {
// handle exception caused by native method modifying control word
DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode;

Expand All @@ -2504,34 +2504,48 @@ LONG WINAPI Handle_FLT_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) {
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_FLT_UNDERFLOW:
case EXCEPTION_FLT_UNDERFLOW: {
PCONTEXT ctx = exceptionInfo->ContextRecord;
#ifndef _WIN64
jint fp_control_word = (* (jint*) StubRoutines::x86::addr_fpu_cntrl_wrd_std());
if (fp_control_word != ctx->FloatSave.ControlWord) {
// Restore FPCW and mask out FLT exceptions
ctx->FloatSave.ControlWord = fp_control_word | 0xffffffc0;
// Mask out pending FLT exceptions
ctx->FloatSave.StatusWord &= 0xffffff00;
return EXCEPTION_CONTINUE_EXECUTION;
return true;
}
#else // !_WIN64
// On Windows, the mxcsr control bits are non-volatile across calls
// See also CR 6192333
//
jint MxCsr = INITIAL_MXCSR;
// we can't use StubRoutines::x86::addr_mxcsr_std()
// because in Win64 mxcsr is not saved there
if (MxCsr != ctx->MxCsr) {
ctx->MxCsr = MxCsr;
return true;
}
#endif // !_WIN64
}
}

return false;
}
#endif

#ifndef _WIN64
static LONG WINAPI Uncaught_Exception_Handler(struct _EXCEPTION_POINTERS* exceptionInfo) {
if (handle_FLT_exception(exceptionInfo)) {
return EXCEPTION_CONTINUE_EXECUTION;
}

// we only override this on 32 bits, so only check it there
if (prev_uef_handler != nullptr) {
// We didn't handle this exception so pass it to the previous
// UnhandledExceptionFilter.
return (prev_uef_handler)(exceptionInfo);
}
#else // !_WIN64
// On Windows, the mxcsr control bits are non-volatile across calls
// See also CR 6192333
//
jint MxCsr = INITIAL_MXCSR;
// we can't use StubRoutines::x86::addr_mxcsr_std()
// because in Win64 mxcsr is not saved there
if (MxCsr != ctx->MxCsr) {
ctx->MxCsr = MxCsr;
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif // !_WIN64

return EXCEPTION_CONTINUE_SEARCH;
}
Expand Down Expand Up @@ -2788,9 +2802,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}

#if defined(_M_AMD64) || defined(_M_IX86)
if ((in_java || in_native) && exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION) {
LONG result=Handle_FLT_Exception(exceptionInfo);
if (result==EXCEPTION_CONTINUE_EXECUTION) return result;
if ((in_java || in_native) && handle_FLT_exception(exceptionInfo)) {
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2023, 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.
*/

/*
* @test id
* @enablePreview
* @requires os.family == "windows"
* @library /test/lib
* @run testng UncaughtNativeExceptionTest
*/

import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import org.testng.annotations.Test;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.regex.Pattern;

import static org.testng.Assert.assertTrue;

public class UncaughtNativeExceptionTest {
private static class Crasher {
public static void main(String[] args) throws Throwable {
System.loadLibrary("NativeException");
throwException();
}

static native void throwException();
}

// check that we actually report the native exception,
// and don't terminate abruptly due to stack overflow error
@Test
public void testNativeExceptionReporting() throws Exception {
OutputAnalyzer output = ProcessTools.executeTestJava(
// executeTestJvm doesn't seem to forward 'java.library.path'
"-Djava.library.path=" + System.getProperty("java.library.path"),
Crasher.class.getName());

File hsErrFile = HsErrFileUtils.openHsErrFileFromOutput(output);
Path hsErrPath = hsErrFile.toPath();
assertTrue(Files.exists(hsErrPath));

Pattern[] positivePatterns = {
Pattern.compile(".*Internal Error \\(0x2a\\).*")
};
HsErrFileUtils.checkHsErrFileContent(hsErrFile, positivePatterns, null, true /* check end marker */, false /* verbose */);
}
}
32 changes: 32 additions & 0 deletions test/hotspot/jtreg/runtime/ErrorHandling/libNativeException.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023, 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.
*/

#include <jni.h>

#include <Windows.h>

const DWORD EX_CODE = 42;

JNIEXPORT void JNICALL Java_UncaughtNativeExceptionTest_00024Crasher_throwException(JNIEnv* env, jclass cls) {
RaiseException(EX_CODE, EXCEPTION_NONCONTINUABLE, 0, NULL);
}

1 comment on commit ed2f5a8

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.