Catch all exceptions on ANCM/IIS border (#864)
This commit is contained in:
parent
1e823d88e2
commit
7977793d4f
|
|
@ -70,7 +70,7 @@ RegisterModule(
|
||||||
DWORD dwServerVersion,
|
DWORD dwServerVersion,
|
||||||
IHttpModuleRegistrationInfo * pModuleInfo,
|
IHttpModuleRegistrationInfo * pModuleInfo,
|
||||||
IHttpServer * pHttpServer
|
IHttpServer * pHttpServer
|
||||||
)
|
) try
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
Routine description:
|
Routine description:
|
||||||
|
|
@ -222,4 +222,4 @@ Finished:
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
CATCH_RETURN()
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@
|
||||||
#include "applicationmanager.h"
|
#include "applicationmanager.h"
|
||||||
#include "applicationinfo.h"
|
#include "applicationinfo.h"
|
||||||
#include "acache.h"
|
#include "acache.h"
|
||||||
#include "hostfxroptions.h"
|
#include "exceptions.h"
|
||||||
|
|
||||||
|
|
||||||
__override
|
__override
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
@ -16,13 +15,12 @@ ASPNET_CORE_PROXY_MODULE_FACTORY::GetHttpModule(
|
||||||
IModuleAllocator * pAllocator
|
IModuleAllocator * pAllocator
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ASPNET_CORE_PROXY_MODULE *pModule = new (pAllocator) ASPNET_CORE_PROXY_MODULE();
|
try
|
||||||
if (pModule == NULL)
|
|
||||||
{
|
{
|
||||||
return E_OUTOFMEMORY;
|
*ppModule = THROW_IF_NULL_ALLOC(new (pAllocator) ASPNET_CORE_PROXY_MODULE());;
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
*ppModule = pModule;
|
CATCH_RETURN();
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__override
|
__override
|
||||||
|
|
@ -82,21 +80,23 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
||||||
REQUEST_NOTIFICATION_STATUS retVal = RQ_NOTIFICATION_CONTINUE;
|
REQUEST_NOTIFICATION_STATUS retVal = RQ_NOTIFICATION_CONTINUE;
|
||||||
IAPPLICATION* pApplication = NULL;
|
IAPPLICATION* pApplication = NULL;
|
||||||
STRU struExeLocation;
|
STRU struExeLocation;
|
||||||
|
try
|
||||||
if (g_fInShutdown)
|
|
||||||
{
|
{
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pApplicationManager = APPLICATION_MANAGER::GetInstance();
|
if (g_fInShutdown)
|
||||||
|
{
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS);
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
hr = pApplicationManager->GetOrCreateApplicationInfo(
|
pApplicationManager = APPLICATION_MANAGER::GetInstance();
|
||||||
g_pHttpServer,
|
|
||||||
|
hr = pApplicationManager->GetOrCreateApplicationInfo(
|
||||||
|
g_pHttpServer,
|
||||||
pHttpContext,
|
pHttpContext,
|
||||||
&m_pApplicationInfo);
|
&m_pApplicationInfo);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,70 +105,76 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
||||||
// Application cannot be started due to wrong hosting mode
|
// Application cannot be started due to wrong hosting mode
|
||||||
// the error should already been logged to window event log for the first request
|
// the error should already been logged to window event log for the first request
|
||||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
// app_offline check to avoid loading aspnetcorerh.dll unnecessarily
|
// app_offline check to avoid loading aspnetcorerh.dll unnecessarily
|
||||||
if (m_pApplicationInfo->AppOfflineFound())
|
if (m_pApplicationInfo->AppOfflineFound())
|
||||||
|
{
|
||||||
|
// servicing app_offline
|
||||||
|
HTTP_DATA_CHUNK DataChunk;
|
||||||
|
IHttpResponse *pResponse = NULL;
|
||||||
|
APP_OFFLINE_HTM *pAppOfflineHtm = NULL;
|
||||||
|
|
||||||
|
pResponse = pHttpContext->GetResponse();
|
||||||
|
pAppOfflineHtm = m_pApplicationInfo->QueryAppOfflineHtm();
|
||||||
|
DBG_ASSERT(pAppOfflineHtm);
|
||||||
|
DBG_ASSERT(pResponse);
|
||||||
|
|
||||||
|
// Ignore failure hresults as nothing we can do
|
||||||
|
// Set fTrySkipCustomErrors to true as we want client see the offline content
|
||||||
|
pResponse->SetStatus(503, "Service Unavailable", 0, hr, NULL, TRUE);
|
||||||
|
pResponse->SetHeader("Content-Type",
|
||||||
|
"text/html",
|
||||||
|
(USHORT)strlen("text/html"),
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
DataChunk.DataChunkType = HttpDataChunkFromMemory;
|
||||||
|
DataChunk.FromMemory.pBuffer = (PVOID)pAppOfflineHtm->m_Contents.QueryStr();
|
||||||
|
DataChunk.FromMemory.BufferLength = pAppOfflineHtm->m_Contents.QueryCB();
|
||||||
|
pResponse->WriteEntityChunkByReference(&DataChunk);
|
||||||
|
|
||||||
|
retVal = RQ_NOTIFICATION_FINISH_REQUEST;
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure assmebly is loaded and application is created
|
||||||
|
hr = m_pApplicationInfo->EnsureApplicationCreated(pHttpContext);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pApplicationInfo->ExtractApplication(&pApplication);
|
||||||
|
|
||||||
|
// make sure application is in running state
|
||||||
|
// cannot recreate the application as we cannot reload clr for inprocess
|
||||||
|
if (pApplication != NULL &&
|
||||||
|
pApplication->QueryStatus() != APPLICATION_STATUS::RUNNING &&
|
||||||
|
pApplication->QueryStatus() != APPLICATION_STATUS::STARTING)
|
||||||
|
{
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create RequestHandler and process the request
|
||||||
|
hr = pApplication->CreateHandler(pHttpContext,
|
||||||
|
&m_pHandler);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = m_pHandler->OnExecuteRequestHandler();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
{
|
{
|
||||||
// servicing app_offline
|
hr = CaughtExceptionHResult();
|
||||||
HTTP_DATA_CHUNK DataChunk;
|
|
||||||
IHttpResponse *pResponse = NULL;
|
|
||||||
APP_OFFLINE_HTM *pAppOfflineHtm = NULL;
|
|
||||||
|
|
||||||
pResponse = pHttpContext->GetResponse();
|
|
||||||
pAppOfflineHtm = m_pApplicationInfo->QueryAppOfflineHtm();
|
|
||||||
DBG_ASSERT(pAppOfflineHtm);
|
|
||||||
DBG_ASSERT(pResponse);
|
|
||||||
|
|
||||||
// Ignore failure hresults as nothing we can do
|
|
||||||
// Set fTrySkipCustomErrors to true as we want client see the offline content
|
|
||||||
pResponse->SetStatus(503, "Service Unavailable", 0, hr, NULL, TRUE);
|
|
||||||
pResponse->SetHeader("Content-Type",
|
|
||||||
"text/html",
|
|
||||||
(USHORT)strlen("text/html"),
|
|
||||||
FALSE
|
|
||||||
);
|
|
||||||
|
|
||||||
DataChunk.DataChunkType = HttpDataChunkFromMemory;
|
|
||||||
DataChunk.FromMemory.pBuffer = (PVOID)pAppOfflineHtm->m_Contents.QueryStr();
|
|
||||||
DataChunk.FromMemory.BufferLength = pAppOfflineHtm->m_Contents.QueryCB();
|
|
||||||
pResponse->WriteEntityChunkByReference(&DataChunk);
|
|
||||||
|
|
||||||
retVal = RQ_NOTIFICATION_FINISH_REQUEST;
|
|
||||||
goto Finished;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure assmebly is loaded and application is created
|
|
||||||
hr = m_pApplicationInfo->EnsureApplicationCreated(pHttpContext);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pApplicationInfo->ExtractApplication(&pApplication);
|
|
||||||
|
|
||||||
// make sure application is in running state
|
|
||||||
// cannot recreate the application as we cannot reload clr for inprocess
|
|
||||||
if (pApplication != NULL &&
|
|
||||||
pApplication->QueryStatus() != APPLICATION_STATUS::RUNNING &&
|
|
||||||
pApplication->QueryStatus() != APPLICATION_STATUS::STARTING)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create RequestHandler and process the request
|
|
||||||
hr = pApplication->CreateHandler(pHttpContext,
|
|
||||||
&m_pHandler);
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
retVal = m_pHandler->OnExecuteRequestHandler();
|
|
||||||
|
|
||||||
Finished:
|
Finished:
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -200,7 +206,16 @@ ASPNET_CORE_PROXY_MODULE::OnAsyncCompletion(
|
||||||
IHttpCompletionInfo * pCompletionInfo
|
IHttpCompletionInfo * pCompletionInfo
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return m_pHandler->OnAsyncCompletion(
|
try
|
||||||
pCompletionInfo->GetCompletionBytes(),
|
{
|
||||||
pCompletionInfo->GetCompletionStatus());
|
return m_pHandler->OnAsyncCompletion(
|
||||||
|
pCompletionInfo->GetCompletionBytes(),
|
||||||
|
pCompletionInfo->GetCompletionStatus());
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// Log exception
|
||||||
|
CaughtExceptionHResult();
|
||||||
|
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="application.h" />
|
<ClInclude Include="application.h" />
|
||||||
<ClInclude Include="config_utility.h" />
|
<ClInclude Include="config_utility.h" />
|
||||||
|
<ClInclude Include="exceptions.h" />
|
||||||
<ClInclude Include="GlobalVersionUtility.h" />
|
<ClInclude Include="GlobalVersionUtility.h" />
|
||||||
<ClInclude Include="fx_ver.h" />
|
<ClInclude Include="fx_ver.h" />
|
||||||
<ClInclude Include="hostfxroptions.h" />
|
<ClInclude Include="hostfxroptions.h" />
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
#include "debugutil.h"
|
#include "debugutil.h"
|
||||||
#include "dbgutil.h"
|
#include "dbgutil.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "stdafx.h"
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
#define ASPNETCORE_DEBUG_FLAG_INFO DEBUG_FLAG_INFO
|
#define ASPNETCORE_DEBUG_FLAG_INFO DEBUG_FLAG_INFO
|
||||||
#define ASPNETCORE_DEBUG_FLAG_WARNING DEBUG_FLAG_WARN
|
#define ASPNETCORE_DEBUG_FLAG_WARNING DEBUG_FLAG_WARN
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
#include "debugutil.h"
|
||||||
|
|
||||||
|
inline VOID ReportUntypedException()
|
||||||
|
{
|
||||||
|
DebugPrint(ASPNETCORE_DEBUG_FLAG_ERROR, "Unhandled non-standard exception");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VOID ReportException(std::exception& exception)
|
||||||
|
{
|
||||||
|
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "Unhandled exception: %s", exception.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline __declspec(noinline) HRESULT CaughtExceptionHResult()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (const std::bad_alloc&)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
catch (std::system_error& exception)
|
||||||
|
{
|
||||||
|
ReportException(exception);
|
||||||
|
return exception.code().value();
|
||||||
|
}
|
||||||
|
catch (std::exception& exception)
|
||||||
|
{
|
||||||
|
ReportException(exception);
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
ReportUntypedException();
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PointerT> auto Throw_IfNullAlloc(PointerT pointer)
|
||||||
|
{
|
||||||
|
if (pointer == nullptr)
|
||||||
|
{
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define RETURN_CAUGHT_EXCEPTION() return CaughtExceptionHResult();
|
||||||
|
#define CATCH_RETURN() catch (...) { RETURN_CAUGHT_EXCEPTION(); }
|
||||||
|
#define THROW_IF_NULL_ALLOC(ptr) Throw_IfNullAlloc(ptr)
|
||||||
|
|
@ -40,4 +40,4 @@
|
||||||
#include "hostfxr_utility.h"
|
#include "hostfxr_utility.h"
|
||||||
#include "EventLog.h"
|
#include "EventLog.h"
|
||||||
#include "hostfxroptions.h"
|
#include "hostfxroptions.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
TEST(CaughtExceptionHResult, ReturnsOutOfMemoryForBadAlloc)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
hr = CaughtExceptionHResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(E_OUTOFMEMORY, hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CaughtExceptionHResult, ReturnsValueForSystemError)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw std::system_error(E_INVALIDARG, std::system_category());
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
hr = CaughtExceptionHResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(E_INVALIDARG, hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CaughtExceptionHResult, ReturnsUhandledExceptionForOtherExceptions)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw E_INVALIDARG;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
hr = CaughtExceptionHResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION), hr);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue