From 0d96354eef8a3149c6feb82186768f50440c59d3 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Mon, 25 Jun 2018 17:12:30 -0700 Subject: [PATCH] Return static 500.30 file on startup fails for in-process (#934) --- .../AspNetCore/src/applicationmanager.cxx | 1 - .../AspNetCore/src/proxymodule.cxx | 6 +- .../CommonLib/SRWExclusiveLock.cpp | 2 +- .../CommonLib/SRWSharedLock.cpp | 2 +- .../InProcessApplicationBase.cpp | 65 +++++++++++++++++ .../InProcessApplicationBase.h | 30 ++++++++ .../InProcessRequestHandler.vcxproj | 6 ++ .../StartupExceptionApplication.cpp | 15 ++++ .../StartupExceptionApplication.h | 70 +++++++++++++++++++ .../StartupExceptionHandler.cpp | 42 +++++++++++ .../StartupExceptionHandler.h | 38 ++++++++++ .../InProcessRequestHandler/dllmain.cxx | 51 +++++--------- .../inprocessapplication.cpp | 66 ++--------------- .../inprocessapplication.h | 20 ++---- .../inprocesshandler.cpp | 22 ------ .../RequestHandlerLib/requesthandler_config.h | 3 +- test/CommonLibTests/CommonLibTests.vcxproj | 8 +-- .../inprocess_application_tests.cpp | 5 +- .../Inprocess/StartupExceptionTests.cs | 20 +++++- .../Inprocess/StartupTests.cs | 2 +- .../StartupExceptionWebSite.csproj | 2 +- 21 files changed, 324 insertions(+), 152 deletions(-) create mode 100644 src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.cpp create mode 100644 src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.h create mode 100644 src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.cpp create mode 100644 src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h create mode 100644 src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.cpp create mode 100644 src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.h diff --git a/src/AspNetCoreModuleV2/AspNetCore/src/applicationmanager.cxx b/src/AspNetCoreModuleV2/AspNetCore/src/applicationmanager.cxx index 9690dcb2fd..01d3e0ecfc 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/src/applicationmanager.cxx +++ b/src/AspNetCoreModuleV2/AspNetCore/src/applicationmanager.cxx @@ -55,7 +55,6 @@ APPLICATION_MANAGER::GetOrCreateApplicationInfo( if (*ppApplicationInfo == NULL) { - pApplicationInfo = new APPLICATION_INFO(); if (pApplicationInfo == NULL) { diff --git a/src/AspNetCoreModuleV2/AspNetCore/src/proxymodule.cxx b/src/AspNetCoreModuleV2/AspNetCore/src/proxymodule.cxx index 96372b48a1..e71a5daf54 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/src/proxymodule.cxx +++ b/src/AspNetCoreModuleV2/AspNetCore/src/proxymodule.cxx @@ -147,8 +147,8 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler( m_pApplicationInfo->ExtractApplication(&pApplication); - // make sure application is in running state - // cannot recreate the application as we cannot reload clr for inprocess + // 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) @@ -156,7 +156,6 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler( hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED); goto Finished; } - // Create RequestHandler and process the request hr = pApplication->CreateHandler(pHttpContext, &m_pHandler); @@ -167,7 +166,6 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler( } retVal = m_pHandler->OnExecuteRequestHandler(); - } catch (...) { diff --git a/src/AspNetCoreModuleV2/CommonLib/SRWExclusiveLock.cpp b/src/AspNetCoreModuleV2/CommonLib/SRWExclusiveLock.cpp index a7e1b53ee0..0bc46b8cf5 100644 --- a/src/AspNetCoreModuleV2/CommonLib/SRWExclusiveLock.cpp +++ b/src/AspNetCoreModuleV2/CommonLib/SRWExclusiveLock.cpp @@ -3,7 +3,7 @@ #include "SRWExclusiveLock.h" -SRWExclusiveLock:: SRWExclusiveLock(const SRWLOCK& lock) +SRWExclusiveLock::SRWExclusiveLock(const SRWLOCK& lock) : m_lock(lock) { AcquireSRWLockExclusive(const_cast(&m_lock)); diff --git a/src/AspNetCoreModuleV2/CommonLib/SRWSharedLock.cpp b/src/AspNetCoreModuleV2/CommonLib/SRWSharedLock.cpp index d561281385..51f88ccbe0 100644 --- a/src/AspNetCoreModuleV2/CommonLib/SRWSharedLock.cpp +++ b/src/AspNetCoreModuleV2/CommonLib/SRWSharedLock.cpp @@ -3,7 +3,7 @@ #include "SRWSharedLock.h" -SRWSharedLock:: SRWSharedLock(const SRWLOCK& lock) +SRWSharedLock::SRWSharedLock(const SRWLOCK& lock) : m_lock(lock) { AcquireSRWLockShared(const_cast(&m_lock)); diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.cpp new file mode 100644 index 0000000000..2f3986a0f5 --- /dev/null +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.cpp @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +#include "InProcessApplicationBase.h" +#include "SRWExclusiveLock.h" + +hostfxr_main_fn InProcessApplicationBase::s_fMainCallback = NULL; + +InProcessApplicationBase::InProcessApplicationBase( + IHttpServer *pHttpServer) + : + m_srwLock(), + m_fRecycleCalled(FALSE), + m_pHttpServer(pHttpServer) +{ + InitializeSRWLock(&m_srwLock); +} + +VOID +InProcessApplicationBase::Recycle( + VOID +) +{ + // We need to guarantee that recycle is only called once, as calling pHttpServer->RecycleProcess + // multiple times can lead to AVs. + if (m_fRecycleCalled) + { + return; + } + + { + SRWExclusiveLock lock(m_srwLock); + + if (m_fRecycleCalled) + { + return; + } + + m_fRecycleCalled = true; + } + + if (!m_pHttpServer->IsCommandLineLaunch()) + { + // IIS scenario. + // We don't actually handle any shutdown logic here. + // Instead, we notify IIS that the process needs to be recycled, which will call + // ApplicationManager->Shutdown(). This will call shutdown on the application. + m_pHttpServer->RecycleProcess(L"AspNetCore InProcess Recycle Process on Demand"); + } + else + { + // IISExpress scenario + // Try to graceful shutdown the managed application + // and call exit to terminate current process + ShutDown(); + // If we set a static callback, we don't want to kill the current process as + // that will kill the test process and means we are running in hostable webcore mode. + if (m_pHttpServer->IsCommandLineLaunch() + && s_fMainCallback == NULL) + { + exit(0); + } + } +} + diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.h new file mode 100644 index 0000000000..defcf3bdf8 --- /dev/null +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessApplicationBase.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +#pragma once + +#include "precomp.hxx" +#include "application.h" +#include "requesthandler_config.h" + +typedef INT(*hostfxr_main_fn) (CONST DWORD argc, CONST PCWSTR argv[]); // TODO these may need to be BSTRs + +class InProcessApplicationBase : public APPLICATION +{ +public: + + InProcessApplicationBase(IHttpServer* pHttpServer); + + ~InProcessApplicationBase() = default; + + VOID Recycle(VOID) override; + +protected: + BOOL m_fRecycleCalled; + SRWLOCK m_srwLock; + IHttpServer* const m_pHttpServer; + // Allows to override call to hostfxr_main with custome callback + // used in testing + static hostfxr_main_fn s_fMainCallback; +}; + diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj index 99a40ce218..907726e2b2 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj @@ -212,14 +212,20 @@ + + + + + + diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.cpp new file mode 100644 index 0000000000..10d6ddb4af --- /dev/null +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.cpp @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +#include "StartupExceptionApplication.h" + +VOID StartupExceptionApplication::ShutDown() +{ + exit(0); +} + +HRESULT StartupExceptionApplication::CreateHandler(IHttpContext *pContext, IREQUEST_HANDLER ** pRequestHandler) +{ + *pRequestHandler = new StartupExceptionHandler(pContext, m_disableLogs, this); + return S_OK; +} diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h new file mode 100644 index 0000000000..52658c8cda --- /dev/null +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +#pragma once + +#include "precomp.hxx" +#include "InProcessApplicationBase.h" +#include "StartupExceptionHandler.h" +#include "SRWExclusiveLock.h" + +class StartupExceptionApplication : public InProcessApplicationBase +{ +public: + StartupExceptionApplication(IHttpServer* pServer, BOOL disableLogs) + : m_disableLogs(disableLogs), + m_pHttpServer(pServer), + InProcessApplicationBase(pServer) + { + InitializeSRWLock(&m_srwLock); + m_status = APPLICATION_STATUS::RUNNING; + } + + ~StartupExceptionApplication() = default; + + virtual VOID ShutDown() override; + virtual HRESULT CreateHandler(IHttpContext * pHttpContext, IREQUEST_HANDLER ** pRequestHandler) override; + + std::string& + GetStaticHtml500Content() + { + { + SRWExclusiveLock lock(m_srwLock); + if (html500Page.empty()) + { + html500Page = std::string(" \ + \ + \ + \ + IIS 500.30 Error \ +
\ +

HTTP Error 500.30 - ANCM In-Process Start Failure

\ +
\ +

Common causes of this issue:

\ +
  • The application failed to start
  • \ +
  • The application started but then stopped
  • \ +
  • The application started but threw an exception during startup
\ +
\ +
\ +

Troubleshooting steps:

\ +
  • Check the system event log for error messages
  • \ +
  • Enable logging the application process' stdout messages
  • \ +
  • Attach a debugger to the application process and inspect
\ +

For more information visit: \ + https://go.microsoft.com/fwlink/?LinkID=808681

\ +
\ +
\ +
"); + } + } + + return html500Page; + } + +private: + std::string html500Page; + SRWLOCK m_srwLock; + BOOL m_disableLogs; + IHttpServer* m_pHttpServer; +}; + diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.cpp new file mode 100644 index 0000000000..b0817a4659 --- /dev/null +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.cpp @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +#include "StartupExceptionHandler.h" + +REQUEST_NOTIFICATION_STATUS StartupExceptionHandler::OnExecuteRequestHandler() +{ + if (!m_disableLogs) + { + HTTP_DATA_CHUNK DataChunk; + IHttpResponse* pResponse = m_pContext->GetResponse(); + pResponse->SetStatus(500, "Internal Server Error", 30, E_FAIL, NULL, TRUE); + pResponse->SetHeader("Content-Type", + "text/html", + (USHORT)strlen("text/html"), + FALSE + ); + const std::string& html500Page = m_pApplication->GetStaticHtml500Content(); + + DataChunk.DataChunkType = HttpDataChunkFromMemory; + DataChunk.FromMemory.pBuffer = (PVOID)html500Page.c_str(); + DataChunk.FromMemory.BufferLength = (ULONG)html500Page.size(); + pResponse->WriteEntityChunkByReference(&DataChunk); + } + else + { + m_pContext->GetResponse()->SetStatus(500, "Internal Server Error", 30, E_FAIL); + } + + return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_FINISH_REQUEST; + +} + +REQUEST_NOTIFICATION_STATUS StartupExceptionHandler::OnAsyncCompletion(DWORD , HRESULT ) +{ + return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_FINISH_REQUEST; +} + +VOID StartupExceptionHandler::TerminateRequest(bool ) +{ + return VOID(); +} diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.h new file mode 100644 index 0000000000..859f3a73f5 --- /dev/null +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionHandler.h @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +#pragma once + +#include "precomp.hxx" +#include "requesthandler.h" +#include "StartupExceptionApplication.h" + +class StartupExceptionApplication; + +class StartupExceptionHandler : public REQUEST_HANDLER +{ +public: + virtual REQUEST_NOTIFICATION_STATUS OnExecuteRequestHandler() override; + + virtual REQUEST_NOTIFICATION_STATUS OnAsyncCompletion(DWORD cbCompletion, HRESULT hrCompletionStatus) override; + + virtual VOID TerminateRequest(bool fClientInitiated) override; + + StartupExceptionHandler(IHttpContext* pContext, BOOL disableLogs, StartupExceptionApplication* pApplication) + : + m_pContext(pContext), + m_disableLogs(disableLogs), + m_pApplication(pApplication) + { + } + + ~StartupExceptionHandler() + { + } + +private: + IHttpContext * m_pContext; + BOOL m_disableLogs; + StartupExceptionApplication* m_pApplication; +}; + diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cxx b/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cxx index 33dad24f03..42d1f2e45f 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cxx +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cxx @@ -8,9 +8,12 @@ #include #include "inprocessapplication.h" +#include "StartupExceptionApplication.h" +#include "inprocesshandler.h" #include "requesthandler_config.h" #include "debugutil.h" #include "resources.h" +#include "exceptions.h" DECLARE_DEBUG_PRINT_OBJECT("aspnetcorev2_inprocess.dll"); @@ -90,46 +93,30 @@ CreateApplication( _Out_ IAPPLICATION **ppApplication ) { - HRESULT hr = S_OK; - IN_PROCESS_APPLICATION *pApplication = NULL; - REQUESTHANDLER_CONFIG *pConfig = NULL; - - // Initialze some global variables here InitializeGlobalConfiguration(pServer); try { - hr = REQUESTHANDLER_CONFIG::CreateRequestHandlerConfig(pServer, pHttpApplication, &pConfig); - if (FAILED(hr)) + REQUESTHANDLER_CONFIG *pConfig = NULL; + RETURN_IF_FAILED(REQUESTHANDLER_CONFIG::CreateRequestHandlerConfig(pServer, pHttpApplication, &pConfig)); + + auto config = std::unique_ptr(pConfig); + + BOOL disableStartupPage = pConfig->QueryDisableStartUpErrorPage(); + + auto pApplication = std::make_unique(pServer, std::move(config)); + + if (FAILED(pApplication->LoadManagedApplication())) { - goto Finished; + // Set the currently running application to a fake application that returns startup exceptions. + *ppApplication = new StartupExceptionApplication(pServer, disableStartupPage); } - - pApplication = new IN_PROCESS_APPLICATION(pServer, pConfig); - - pConfig = NULL; - - *ppApplication = pApplication; - } - catch (std::bad_alloc&) - { - hr = E_OUTOFMEMORY; - } - -Finished: - if (FAILED(hr)) - { - if (pApplication != NULL) + else { - delete pApplication; - pApplication = NULL; - } - if (pConfig != NULL) - { - delete pConfig; - pConfig = NULL; + *ppApplication = pApplication.release(); } } + CATCH_RETURN(); - return hr; + return S_OK; } diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp index 4a3fd9901d..caf55a20f1 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp @@ -13,39 +13,30 @@ #include "exceptions.h" IN_PROCESS_APPLICATION* IN_PROCESS_APPLICATION::s_Application = NULL; -hostfxr_main_fn IN_PROCESS_APPLICATION::s_fMainCallback = NULL; IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION( IHttpServer *pHttpServer, - REQUESTHANDLER_CONFIG *pConfig) : + std::unique_ptr pConfig) : m_pHttpServer(pHttpServer), m_ProcessExitCode(0), m_fBlockCallbacksIntoManaged(FALSE), m_fInitialized(FALSE), m_fShutdownCalledFromNative(FALSE), m_fShutdownCalledFromManaged(FALSE), - m_srwLock() + InProcessApplicationBase(pHttpServer), + m_pConfig(std::move(pConfig)) { // is it guaranteed that we have already checked app offline at this point? // If so, I don't think there is much to do here. DBG_ASSERT(pHttpServer != NULL); DBG_ASSERT(pConfig != NULL); - InitializeSRWLock(&m_srwLock); - m_pConfig = pConfig; m_status = APPLICATION_STATUS::STARTING; } IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION() { - - if (m_pConfig != NULL) - { - delete m_pConfig; - m_pConfig = NULL; - } - m_hThread = NULL; s_Application = NULL; } @@ -129,7 +120,6 @@ Finished: } } - VOID IN_PROCESS_APPLICATION::ShutDownInternal() { @@ -205,54 +195,6 @@ IN_PROCESS_APPLICATION::ShutDownInternal() s_Application = NULL; } -__override -VOID -IN_PROCESS_APPLICATION::Recycle( - VOID -) -{ - // We need to guarantee that recycle is only called once, as calling pHttpServer->RecycleProcess - // multiple times can lead to AVs. - if (m_fRecycleCalled) - { - return; - } - - { - SRWExclusiveLock lock(m_srwLock); - - if (m_fRecycleCalled) - { - return; - } - - m_fRecycleCalled = true; - } - - if (!m_pHttpServer->IsCommandLineLaunch()) - { - // IIS scenario. - // We don't actually handle any shutdown logic here. - // Instead, we notify IIS that the process needs to be recycled, which will call - // ApplicationManager->Shutdown(). This will call shutdown on the application. - m_pHttpServer->RecycleProcess(L"AspNetCore InProcess Recycle Process on Demand"); - } - else - { - // IISExpress scenario - // Try to graceful shutdown the managed application - // and call exit to terminate current process - ShutDown(); - - // If we set a static callback, we don't want to kill the current process as - // that will kill the test process and means we are running in hostable webcore mode. - if (s_fMainCallback == NULL) - { - exit(0); - } - } -} - REQUEST_NOTIFICATION_STATUS IN_PROCESS_APPLICATION::OnAsyncCompletion( DWORD cbCompletion, @@ -712,7 +654,7 @@ IN_PROCESS_APPLICATION::RunDotnetApplication(DWORD argc, CONST PCWSTR* argv, hos REQUESTHANDLER_CONFIG* IN_PROCESS_APPLICATION::QueryConfig() const { - return m_pConfig; + return m_pConfig.get(); } HRESULT diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h index 0713ff5016..c80ca92d0c 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h @@ -4,22 +4,21 @@ #pragma once #include "precomp.hxx" -#include "application.h" +#include "InProcessApplicationBase.h" #include "inprocesshandler.h" #include "requesthandler_config.h" -typedef INT(*hostfxr_main_fn) (CONST DWORD argc, CONST PCWSTR argv[]); // TODO these may need to be BSTRs typedef REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_REQUEST_HANDLER) (IN_PROCESS_HANDLER* pInProcessHandler, void* pvRequestHandlerContext); typedef BOOL(WINAPI * PFN_SHUTDOWN_HANDLER) (void* pvShutdownHandlerContext); typedef REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_MANAGED_CONTEXT_HANDLER)(void *pvManagedHttpContext, HRESULT hrCompletionStatus, DWORD cbCompletion); -class IN_PROCESS_APPLICATION : public APPLICATION +class IN_PROCESS_APPLICATION : public InProcessApplicationBase { public: IN_PROCESS_APPLICATION( IHttpServer* pHttpServer, - REQUESTHANDLER_CONFIG *pConfig); + std::unique_ptr pConfig); ~IN_PROCESS_APPLICATION(); @@ -36,12 +35,6 @@ public: _In_ VOID* pvShutdownHandlerContext ); - __override - VOID - Recycle( - VOID - ); - __override HRESULT CreateHandler( @@ -163,7 +156,6 @@ private: BOOL m_fRecycleCalled; BOOL m_fInitialized; - SRWLOCK m_srwLock; // Thread for capturing startup stderr logs when logging is disabled HANDLE m_hErrThread; @@ -172,11 +164,9 @@ private: static IN_PROCESS_APPLICATION* s_Application; IOutputManager* m_pLoggerProvider; - REQUESTHANDLER_CONFIG* m_pConfig; + std::unique_ptr m_pConfig; + - // Allows to override call to hostfxr_main with custome callback - // used in testing - static hostfxr_main_fn s_fMainCallback; static VOID diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp index 5678e2c4fd..5c7d9571da 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp @@ -23,28 +23,6 @@ __override REQUEST_NOTIFICATION_STATUS IN_PROCESS_HANDLER::OnExecuteRequestHandler() { - // First get the in process Application - HRESULT hr; - - hr = m_pApplication->LoadManagedApplication(); - - if (FAILED(hr)) - { - // TODO remove com_error? - /*_com_error err(hr); - if (ANCMEvents::ANCM_START_APPLICATION_FAIL::IsEnabled(m_pW3Context->GetTraceContext())) - { - ANCMEvents::ANCM_START_APPLICATION_FAIL::RaiseEvent( - m_pW3Context->GetTraceContext(), - NULL, - err.ErrorMessage()); - } - */ - //fInternalError = TRUE; - m_pW3Context->GetResponse()->SetStatus(500, "Internal Server Error", 0, hr); - return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_FINISH_REQUEST; - } - // FREB log if (ANCMEvents::ANCM_START_APPLICATION_SUCCESS::IsEnabled(m_pW3Context->GetTraceContext())) diff --git a/src/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h b/src/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h index 71f5cb6e66..60cbd7c8b7 100644 --- a/src/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h +++ b/src/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h @@ -53,9 +53,8 @@ enum APP_HOSTING_MODEL class REQUESTHANDLER_CONFIG { public: - virtual - ~REQUESTHANDLER_CONFIG(); + ~REQUESTHANDLER_CONFIG(); static HRESULT diff --git a/test/CommonLibTests/CommonLibTests.vcxproj b/test/CommonLibTests/CommonLibTests.vcxproj index 5117512c47..906518c621 100644 --- a/test/CommonLibTests/CommonLibTests.vcxproj +++ b/test/CommonLibTests/CommonLibTests.vcxproj @@ -101,7 +101,7 @@ true Console ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;%(AdditionalDependencies) @@ -127,7 +127,7 @@ true Console ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;%(AdditionalDependencies) @@ -153,7 +153,7 @@ true true ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;%(AdditionalDependencies) @@ -179,7 +179,7 @@ true true ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;%(AdditionalDependencies) diff --git a/test/CommonLibTests/inprocess_application_tests.cpp b/test/CommonLibTests/inprocess_application_tests.cpp index 98326312f1..d362b8f56c 100644 --- a/test/CommonLibTests/inprocess_application_tests.cpp +++ b/test/CommonLibTests/inprocess_application_tests.cpp @@ -16,7 +16,8 @@ namespace InprocessTests { auto server = new MockHttpServer(); auto requestHandlerConfig = MockRequestHandlerConfig::CreateConfig(); - IN_PROCESS_APPLICATION *app = new IN_PROCESS_APPLICATION(server, requestHandlerConfig); + auto config = std::unique_ptr(requestHandlerConfig); + IN_PROCESS_APPLICATION *app = new IN_PROCESS_APPLICATION(server, std::move(config)); { std::wstring exePath(L"hello"); app->SetParameter(L"InProcessExeLocation", exePath.c_str()); @@ -24,5 +25,3 @@ namespace InprocessTests ASSERT_STREQ(app->QueryExeLocation(), L"hello"); } } - - diff --git a/test/IISIntegration.FunctionalTests/Inprocess/StartupExceptionTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/StartupExceptionTests.cs index d82877d20c..0b09c7a465 100644 --- a/test/IISIntegration.FunctionalTests/Inprocess/StartupExceptionTests.cs +++ b/test/IISIntegration.FunctionalTests/Inprocess/StartupExceptionTests.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Net; using System.Threading.Tasks; using IISIntegration.FunctionalTests.Utilities; using Xunit; -using System.Net; namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests { @@ -18,7 +18,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests public async Task CheckStdoutWithRandomNumber(string path) { var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite"); - deploymentParameters.PublishApplicationBeforeDeployment = true; deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path; var randomNumberString = new Random(Guid.NewGuid().GetHashCode()).Next(10000000).ToString(); deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_RANDOM_VALUE"] = randomNumberString; @@ -42,8 +41,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests public async Task CheckStdoutWithLargeWrites(string path) { var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite"); - deploymentParameters.PublishApplicationBeforeDeployment = true; deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path; + var deploymentResult = await DeployAsync(deploymentParameters); var response = await deploymentResult.RetryingHttpClient.GetAsync(path); @@ -54,5 +53,20 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests Assert.Contains(TestSink.Writes, context => context.Message.Contains(new string('a', 4096))); } + + [Fact] + public async Task Gets500_30_ErrorPage() + { + var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite"); + + var deploymentResult = await DeployAsync(deploymentParameters); + + var response = await deploymentResult.HttpClient.GetAsync("/"); + Assert.False(response.IsSuccessStatusCode); + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + + var responseText = await response.Content.ReadAsStringAsync(); + Assert.Contains("500.30 - ANCM In-Process Start Failure", responseText); + } } } diff --git a/test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs b/test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs index 68fac580db..f848ab910a 100644 --- a/test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs +++ b/test/IISIntegration.FunctionalTests/Inprocess/StartupTests.cs @@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests var deploymentParameters = new DeploymentParameters(variant) { ApplicationPath = Helpers.GetInProcessTestSitesPath(), - PublishApplicationBeforeDeployment = true, + PublishApplicationBeforeDeployment = true }; var deploymentResult = await DeployAsync(deploymentParameters); diff --git a/test/WebSites/StartupExceptionWebSite/StartupExceptionWebSite.csproj b/test/WebSites/StartupExceptionWebSite/StartupExceptionWebSite.csproj index 2b9db3ce4a..d279ce41b4 100644 --- a/test/WebSites/StartupExceptionWebSite/StartupExceptionWebSite.csproj +++ b/test/WebSites/StartupExceptionWebSite/StartupExceptionWebSite.csproj @@ -1,4 +1,4 @@ - +