Improve Windows page fault handler.

- Re-throw exception if not access violation exception.
- If pointer is not within known pointers also re-throw.

Change-Id: I01461f550994e32c9e8757b0344e70f2195612fb
Signed-off-by: Mrozek, Michal <michal.mrozek@intel.com>
This commit is contained in:
Mrozek, Michal
2019-09-06 11:57:39 +02:00
committed by sys_ocldev
parent 093bc4da9c
commit d4571d685a
3 changed files with 34 additions and 6 deletions

View File

@@ -18,10 +18,14 @@ std::function<LONG(struct _EXCEPTION_POINTERS *exceptionInfo)> PageFaultManagerW
PageFaultManagerWindows::PageFaultManagerWindows() { PageFaultManagerWindows::PageFaultManagerWindows() {
pageFaultHandler = [&](struct _EXCEPTION_POINTERS *exceptionInfo) { pageFaultHandler = [&](struct _EXCEPTION_POINTERS *exceptionInfo) {
if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && !this->verifyPageFault(reinterpret_cast<void *>(exceptionInfo->ExceptionRecord->ExceptionInformation[1]))) { if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
return EXCEPTION_CONTINUE_SEARCH; if (this->verifyPageFault(reinterpret_cast<void *>(exceptionInfo->ExceptionRecord->ExceptionInformation[1]))) {
//this is our fault that we serviced, continue app execution
return EXCEPTION_CONTINUE_EXECUTION;
}
} }
return EXCEPTION_CONTINUE_EXECUTION; //not our exception
return EXCEPTION_CONTINUE_SEARCH;
}; };
previousHandler = AddVectoredExceptionHandler(1, pageFaultHandlerWrapper); previousHandler = AddVectoredExceptionHandler(1, pageFaultHandlerWrapper);

View File

@@ -69,9 +69,10 @@ class MockPageFaultManagerHandlerInvoke : public T {
if (allowCPUMemoryAccessOnPageFault) { if (allowCPUMemoryAccessOnPageFault) {
this->allowCPUMemoryAccess(ptr, size); this->allowCPUMemoryAccess(ptr, size);
} }
return true; return returnStatus;
} }
bool returnStatus = true;
bool allowCPUMemoryAccessOnPageFault = false; bool allowCPUMemoryAccessOnPageFault = false;
bool handlerInvoked = false; bool handlerInvoked = false;
size_t size = 65536; size_t size = 65536;

View File

@@ -14,14 +14,37 @@
using namespace NEO; using namespace NEO;
using MockPageFaultManagerWindows = MockPageFaultManagerHandlerInvoke<PageFaultManagerWindows>; using MockPageFaultManagerWindows = MockPageFaultManagerHandlerInvoke<PageFaultManagerWindows>;
bool raiseException(NTSTATUS type) {
__try {
RaiseException(type, 0, 0, NULL);
} __except (EXCEPTION_EXECUTE_HANDLER) {
return true;
}
return false;
}
TEST(PageFaultManagerWindowsTest, whenPageFaultIsRaisedThenHandlerIsInvoked) { TEST(PageFaultManagerWindowsTest, whenPageFaultIsRaisedThenHandlerIsInvoked) {
auto pageFaultManager = std::make_unique<MockPageFaultManagerWindows>(); auto pageFaultManager = std::make_unique<MockPageFaultManagerWindows>();
EXPECT_FALSE(pageFaultManager->handlerInvoked); EXPECT_FALSE(pageFaultManager->handlerInvoked);
EXPECT_FALSE(raiseException(EXCEPTION_ACCESS_VIOLATION));
RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL);
EXPECT_TRUE(pageFaultManager->handlerInvoked); EXPECT_TRUE(pageFaultManager->handlerInvoked);
} }
TEST(PageFaultManagerWindowsTest, whenExceptionAccessViolationIsRaisedButPointerIsNotKnownThenExceptionIsRethrown) {
auto pageFaultManager = std::make_unique<MockPageFaultManagerWindows>();
EXPECT_FALSE(pageFaultManager->handlerInvoked);
pageFaultManager->returnStatus = false;
EXPECT_TRUE(raiseException(EXCEPTION_ACCESS_VIOLATION));
EXPECT_TRUE(pageFaultManager->handlerInvoked);
}
TEST(PageFaultManagerWindowsTest, whenExceptionOtherThanAccessViolationIsRaisedThenExceptionIsRethrownAndHandlerIsNotInvoked) {
auto pageFaultManager = std::make_unique<MockPageFaultManagerWindows>();
EXPECT_FALSE(pageFaultManager->handlerInvoked);
EXPECT_TRUE(raiseException(EXCEPTION_DATATYPE_MISALIGNMENT));
EXPECT_FALSE(pageFaultManager->handlerInvoked);
}
TEST(PageFaultManagerWindowsTest, givenProtectedMemoryWhenTryingToAccessThenPageFaultIsRaisedAndMemoryIsAccessibleAfterHandling) { TEST(PageFaultManagerWindowsTest, givenProtectedMemoryWhenTryingToAccessThenPageFaultIsRaisedAndMemoryIsAccessibleAfterHandling) {
auto pageFaultManager = std::make_unique<MockPageFaultManagerWindows>(); auto pageFaultManager = std::make_unique<MockPageFaultManagerWindows>();
pageFaultManager->allowCPUMemoryAccessOnPageFault = true; pageFaultManager->allowCPUMemoryAccessOnPageFault = true;