JDK-8185734 : [Windows] Structured Exception Catcher missing around gtest execution
  • Type: Bug
  • Component: hotspot
  • Sub-Component: test
  • Affected Version: 9,15
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows
  • CPU: x86
  • Submitted: 2017-08-02
  • Updated: 2025-01-21
  • Resolved: 2020-12-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 17
11.0.12Fixed 17 b02Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
When running gtests on Windows, there is no __try/__except handler around the test execution.  As a result, SafeFetch32/SafeFetchN does not work properly on 32bit Windows during gtest execution.  There might be other error handling related issues as well, but it was SafeFetch not working that uncovered the problem.

This problem is very similar to JDK-8074860.  Some of the infrastructure mentioned there (os::win32::call_test_func_with_wrapper() and such) was removed by that change.  Since the tests in question were run during VM initialization, and that change made VM initialization properly protected, that infrastructure was no longer needed.  But with gtest we've moved a bunch of those tests out of the VM initialization context, and they are no longer protected.

I think conditionally wrapping the call to RUN_ALL_TESTS() in gtestMain.cpp with a __try/__except block using topLevelExceptionFilter will address this problem.  For the conditionalization, I suggest using the existing GTEST_HAS_SEH macro.

Comments
Fix Request (11u): I'd like to fix this in an effort to make gtests on Windows more stable. Original PR: https://git.openjdk.java.net/jdk/pull/1757 Original patch: https://github.com/openjdk/jdk/commit/568dc29b.diff I would like to downport it since it allows us to run gtests which test signal handling on Windows in 11u. 11u patch: http://cr.openjdk.java.net/~stuefe/webrevs/backports/8185734-Windows-Structured-Exception-Catcher-missing-around-gtest-execution-11u.diff RFR-Thread: https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2021-May/006117.html The original patch does not apply cleanly due to changes done in GTestWrapper.java in the wake of JEP 387. However, the delta is minimal (just one line). Patch has been tested at SAP for some weeks now. Thanks, Thomas
19-05-2021

Changeset: 568dc29b Author: Thomas Stuefe <stuefe@openjdk.org> Date: 2020-12-15 09:02:46 +0000 URL: https://git.openjdk.java.net/jdk/commit/568dc29b
15-12-2020

Overriding GTEST_HAS_SEH is not an option since if you have death tests you need SEH. Setting GTEST_HAS_SEH=0 makes the gtest build fail.
13-12-2020

The special case of SafeFetch on x64 is currently handled by HandleExceptionFromCodeCache(). Any fault occurring caused by code in the code cache is thereby relegated to the topLevelExceptionHandler and handled correctly, and since SafeFetch uses a generated StubRoutine this works for SafeFetch too. Only works for x64, not for x86, since this code was introduced on x64 only for the changed SEH model (which separates stack meta information from the stack and makes it necessary to tell the Unwinder where the code lives). So, SafeFetch from x86 still faults gtests, as do any real faults. Not sure about aarch64. They use VEH for everything. They may have no problem at all with faults in gtests, but I do not have the hardware to try.
11-12-2020

Did some experiments: 1) wrapping `__try{}__except(topLevelExceptionFilter)` around the whole runner in gtestLauncher.cpp can be done (it requires exporting the handler from the DLL) but does not do any good. Since the SEH handler of the google test framework is chained below that handler and will get any fault first. Results in the generic "SEH .. thrown in test body", our handler does not get control. 2) Wrapping any point below that is difficult since the use of __try .. __except excludes the use of C++ exceptions. Since gtest communicates test errors with exceptions, we cannot wrap anything above TEST_VM... level. The only way I see for solving either to switch to VectoredExceptionHandling. Or, to somehow disable the google test SEH handling and go with (1).
10-12-2020

ILW=exception handling doesn't work as expected;gtest tests, windows x86;none=MLH=>P4
10-10-2017

Use SafeFetch32 (after VM initialization) to read some invalid location. Address zero might be a good reliable choice to generate a crash.
02-08-2017

ok, can you provide the steps for reproducing the problems you faced?
02-08-2017

[~iignatyev] Nope. I got here and filed this bug after running into problems in a TEST_VM test. The thread context matters, e.g. the __try/__except needs to be active on the stack when the failure occurs.
02-08-2017

my understanding of JDK-8074860 was that we might have a problem only when there is no initialized JVM yet. in gtest context, we can bump into it only in "real unit" tests, i.e. tests which run w/o pre-initialized JVM.
02-08-2017

[~iignatyev] "wrap execution of tests which don't init jvm" -- that's backward. It should be all test executions, or at least those with an initialized VM if toplevelExceptionFilter requires that.
02-08-2017

I see, I misread http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/883ae015914d . so we need to either wrap execution of tests which don't init jvm or the whole test execution. I've glanced at topLevelExceptionFilter, it seems to be safe to use w/ uninitialized JVM.
02-08-2017

[~iignatyev] No, that's not enough. JNI_CreateJavaVM already itself wraps its body as needed (per JDK-8074860). That's why the wrapping of the tests when they were executed as part of VM initialization was no longer needed. But the gtests are run in a different execution context. See runUnitTestsInner, which (via init_jvm) calls JNI_CreateJavaVM, and then later calls RUN_ALL_TESTS(). A possible complication is that I don't know if toplevelExceptionFilter requires an initialized VM. It might be we can't use it when running tests that don't require a VM.
02-08-2017

[~kbarrett], will it be enough to just wrap JNI_CreateJavaVM in hotspot/test/native/gtestMain.cpp?
02-08-2017