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: dholmes, djelinski
  • Loading branch information
JornVernee committed Sep 21, 2023
1 parent 349723c commit 38bf119
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 @@ -1504,6 +1504,8 @@ else
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libCompleteExit += -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 @@ -2534,9 +2536,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 @@ -2547,34 +2547,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 @@ -2831,9 +2845,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.executeTestJvm(
// 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);
}

3 comments on commit 38bf119

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

@GoeLin
Copy link
Member

@GoeLin GoeLin commented on 38bf119 Apr 19, 2024

Choose a reason for hiding this comment

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

/backport jdk21u-dev

@openjdk
Copy link

@openjdk openjdk bot commented on 38bf119 Apr 19, 2024

Choose a reason for hiding this comment

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

@GoeLin the backport was successfully created on the branch backport-GoeLin-38bf1192 in my personal fork of openjdk/jdk21u-dev. To create a pull request with this backport targeting openjdk/jdk21u-dev:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit 38bf1192 from the openjdk/jdk repository.

The commit being backported was authored by Jorn Vernee on 21 Sep 2023 and was reviewed by David Holmes and Daniel Jeliński.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk21u-dev:

$ git fetch https://github.com/openjdk-bots/jdk21u-dev.git backport-GoeLin-38bf1192:backport-GoeLin-38bf1192
$ git checkout backport-GoeLin-38bf1192
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk21u-dev.git backport-GoeLin-38bf1192

Please sign in to comment.