Return static 500.30 file on startup fails for in-process (#934)
This commit is contained in:
parent
4a0691a36c
commit
0d96354eef
|
|
@ -55,7 +55,6 @@ APPLICATION_MANAGER::GetOrCreateApplicationInfo(
|
||||||
|
|
||||||
if (*ppApplicationInfo == NULL)
|
if (*ppApplicationInfo == NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
pApplicationInfo = new APPLICATION_INFO();
|
pApplicationInfo = new APPLICATION_INFO();
|
||||||
if (pApplicationInfo == NULL)
|
if (pApplicationInfo == NULL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -147,8 +147,8 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
||||||
|
|
||||||
m_pApplicationInfo->ExtractApplication(&pApplication);
|
m_pApplicationInfo->ExtractApplication(&pApplication);
|
||||||
|
|
||||||
// make sure application is in running state
|
// make sure application is in running state
|
||||||
// cannot recreate the application as we cannot reload clr for inprocess
|
// cannot recreate the application as we cannot reload clr for inprocess
|
||||||
if (pApplication != NULL &&
|
if (pApplication != NULL &&
|
||||||
pApplication->QueryStatus() != APPLICATION_STATUS::RUNNING &&
|
pApplication->QueryStatus() != APPLICATION_STATUS::RUNNING &&
|
||||||
pApplication->QueryStatus() != APPLICATION_STATUS::STARTING)
|
pApplication->QueryStatus() != APPLICATION_STATUS::STARTING)
|
||||||
|
|
@ -156,7 +156,6 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create RequestHandler and process the request
|
// Create RequestHandler and process the request
|
||||||
hr = pApplication->CreateHandler(pHttpContext,
|
hr = pApplication->CreateHandler(pHttpContext,
|
||||||
&m_pHandler);
|
&m_pHandler);
|
||||||
|
|
@ -167,7 +166,6 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
retVal = m_pHandler->OnExecuteRequestHandler();
|
retVal = m_pHandler->OnExecuteRequestHandler();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "SRWExclusiveLock.h"
|
#include "SRWExclusiveLock.h"
|
||||||
|
|
||||||
SRWExclusiveLock:: SRWExclusiveLock(const SRWLOCK& lock)
|
SRWExclusiveLock::SRWExclusiveLock(const SRWLOCK& lock)
|
||||||
: m_lock(lock)
|
: m_lock(lock)
|
||||||
{
|
{
|
||||||
AcquireSRWLockExclusive(const_cast<SRWLOCK*>(&m_lock));
|
AcquireSRWLockExclusive(const_cast<SRWLOCK*>(&m_lock));
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "SRWSharedLock.h"
|
#include "SRWSharedLock.h"
|
||||||
|
|
||||||
SRWSharedLock:: SRWSharedLock(const SRWLOCK& lock)
|
SRWSharedLock::SRWSharedLock(const SRWLOCK& lock)
|
||||||
: m_lock(lock)
|
: m_lock(lock)
|
||||||
{
|
{
|
||||||
AcquireSRWLockShared(const_cast<SRWLOCK*>(&m_lock));
|
AcquireSRWLockShared(const_cast<SRWLOCK*>(&m_lock));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -212,14 +212,20 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="aspnetcore_event.h" />
|
<ClInclude Include="aspnetcore_event.h" />
|
||||||
<ClInclude Include="inprocessapplication.h" />
|
<ClInclude Include="inprocessapplication.h" />
|
||||||
|
<ClInclude Include="InProcessApplicationBase.h" />
|
||||||
<ClInclude Include="inprocesshandler.h" />
|
<ClInclude Include="inprocesshandler.h" />
|
||||||
<ClInclude Include="precomp.hxx" />
|
<ClInclude Include="precomp.hxx" />
|
||||||
|
<ClInclude Include="StartupExceptionApplication.h" />
|
||||||
|
<ClInclude Include="StartupExceptionHandler.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dllmain.cxx" />
|
<ClCompile Include="dllmain.cxx" />
|
||||||
<ClCompile Include="inprocessapplication.cpp" />
|
<ClCompile Include="inprocessapplication.cpp" />
|
||||||
|
<ClCompile Include="InProcessApplicationBase.cpp" />
|
||||||
<ClCompile Include="inprocesshandler.cpp" />
|
<ClCompile Include="inprocesshandler.cpp" />
|
||||||
<ClCompile Include="managedexports.cxx" />
|
<ClCompile Include="managedexports.cxx" />
|
||||||
|
<ClCompile Include="StartupExceptionApplication.cpp" />
|
||||||
|
<ClCompile Include="StartupExceptionHandler.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\CommonLib\CommonLib.vcxproj">
|
<ProjectReference Include="..\CommonLib\CommonLib.vcxproj">
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> \
|
||||||
|
<html xmlns=\"http://www.w3.org/1999/xhtml\"> \
|
||||||
|
<head> \
|
||||||
|
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" /> \
|
||||||
|
<title> IIS 500.30 Error </title><style type=\"text/css\"></style></head> \
|
||||||
|
<body> <div id = \"content\"> \
|
||||||
|
<div class = \"content-container\"><h3> HTTP Error 500.30 - ANCM In-Process Start Failure </h3></div> \
|
||||||
|
<div class = \"content-container\"> \
|
||||||
|
<fieldset> <h4> Common causes of this issue: </h4> \
|
||||||
|
<ul><li> The application failed to start </li> \
|
||||||
|
<li> The application started but then stopped </li> \
|
||||||
|
<li> The application started but threw an exception during startup </li></ul></fieldset> \
|
||||||
|
</div> \
|
||||||
|
<div class = \"content-container\"> \
|
||||||
|
<fieldset><h4> Troubleshooting steps: </h4> \
|
||||||
|
<ul><li> Check the system event log for error messages </li> \
|
||||||
|
<li> Enable logging the application process' stdout messages </li> \
|
||||||
|
<li> Attach a debugger to the application process and inspect </li></ul></fieldset> \
|
||||||
|
<fieldset><h4> For more information visit: \
|
||||||
|
<a href=\"https://go.microsoft.com/fwlink/?LinkID=808681\"> <cite> https://go.microsoft.com/fwlink/?LinkID=808681 </cite></a></h4> \
|
||||||
|
</fieldset> \
|
||||||
|
</div> \
|
||||||
|
</div></body></html>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return html500Page;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string html500Page;
|
||||||
|
SRWLOCK m_srwLock;
|
||||||
|
BOOL m_disableLogs;
|
||||||
|
IHttpServer* m_pHttpServer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -8,9 +8,12 @@
|
||||||
#include <VersionHelpers.h>
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
#include "inprocessapplication.h"
|
#include "inprocessapplication.h"
|
||||||
|
#include "StartupExceptionApplication.h"
|
||||||
|
#include "inprocesshandler.h"
|
||||||
#include "requesthandler_config.h"
|
#include "requesthandler_config.h"
|
||||||
#include "debugutil.h"
|
#include "debugutil.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
||||||
DECLARE_DEBUG_PRINT_OBJECT("aspnetcorev2_inprocess.dll");
|
DECLARE_DEBUG_PRINT_OBJECT("aspnetcorev2_inprocess.dll");
|
||||||
|
|
||||||
|
|
@ -90,46 +93,30 @@ CreateApplication(
|
||||||
_Out_ IAPPLICATION **ppApplication
|
_Out_ IAPPLICATION **ppApplication
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
|
||||||
IN_PROCESS_APPLICATION *pApplication = NULL;
|
|
||||||
REQUESTHANDLER_CONFIG *pConfig = NULL;
|
|
||||||
|
|
||||||
// Initialze some global variables here
|
|
||||||
InitializeGlobalConfiguration(pServer);
|
InitializeGlobalConfiguration(pServer);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hr = REQUESTHANDLER_CONFIG::CreateRequestHandlerConfig(pServer, pHttpApplication, &pConfig);
|
REQUESTHANDLER_CONFIG *pConfig = NULL;
|
||||||
if (FAILED(hr))
|
RETURN_IF_FAILED(REQUESTHANDLER_CONFIG::CreateRequestHandlerConfig(pServer, pHttpApplication, &pConfig));
|
||||||
|
|
||||||
|
auto config = std::unique_ptr<REQUESTHANDLER_CONFIG>(pConfig);
|
||||||
|
|
||||||
|
BOOL disableStartupPage = pConfig->QueryDisableStartUpErrorPage();
|
||||||
|
|
||||||
|
auto pApplication = std::make_unique<IN_PROCESS_APPLICATION>(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);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
delete pApplication;
|
*ppApplication = pApplication.release();
|
||||||
pApplication = NULL;
|
|
||||||
}
|
|
||||||
if (pConfig != NULL)
|
|
||||||
{
|
|
||||||
delete pConfig;
|
|
||||||
pConfig = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CATCH_RETURN();
|
||||||
|
|
||||||
return hr;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,39 +13,30 @@
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
|
||||||
IN_PROCESS_APPLICATION* IN_PROCESS_APPLICATION::s_Application = NULL;
|
IN_PROCESS_APPLICATION* IN_PROCESS_APPLICATION::s_Application = NULL;
|
||||||
hostfxr_main_fn IN_PROCESS_APPLICATION::s_fMainCallback = NULL;
|
|
||||||
|
|
||||||
IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION(
|
IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION(
|
||||||
IHttpServer *pHttpServer,
|
IHttpServer *pHttpServer,
|
||||||
REQUESTHANDLER_CONFIG *pConfig) :
|
std::unique_ptr<REQUESTHANDLER_CONFIG> pConfig) :
|
||||||
m_pHttpServer(pHttpServer),
|
m_pHttpServer(pHttpServer),
|
||||||
m_ProcessExitCode(0),
|
m_ProcessExitCode(0),
|
||||||
m_fBlockCallbacksIntoManaged(FALSE),
|
m_fBlockCallbacksIntoManaged(FALSE),
|
||||||
m_fInitialized(FALSE),
|
m_fInitialized(FALSE),
|
||||||
m_fShutdownCalledFromNative(FALSE),
|
m_fShutdownCalledFromNative(FALSE),
|
||||||
m_fShutdownCalledFromManaged(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?
|
// 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.
|
// If so, I don't think there is much to do here.
|
||||||
DBG_ASSERT(pHttpServer != NULL);
|
DBG_ASSERT(pHttpServer != NULL);
|
||||||
DBG_ASSERT(pConfig != NULL);
|
DBG_ASSERT(pConfig != NULL);
|
||||||
|
|
||||||
InitializeSRWLock(&m_srwLock);
|
|
||||||
m_pConfig = pConfig;
|
|
||||||
|
|
||||||
m_status = APPLICATION_STATUS::STARTING;
|
m_status = APPLICATION_STATUS::STARTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
|
IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_pConfig != NULL)
|
|
||||||
{
|
|
||||||
delete m_pConfig;
|
|
||||||
m_pConfig = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_hThread = NULL;
|
m_hThread = NULL;
|
||||||
s_Application = NULL;
|
s_Application = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +120,6 @@ Finished:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
IN_PROCESS_APPLICATION::ShutDownInternal()
|
IN_PROCESS_APPLICATION::ShutDownInternal()
|
||||||
{
|
{
|
||||||
|
|
@ -205,54 +195,6 @@ IN_PROCESS_APPLICATION::ShutDownInternal()
|
||||||
s_Application = NULL;
|
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
|
REQUEST_NOTIFICATION_STATUS
|
||||||
IN_PROCESS_APPLICATION::OnAsyncCompletion(
|
IN_PROCESS_APPLICATION::OnAsyncCompletion(
|
||||||
DWORD cbCompletion,
|
DWORD cbCompletion,
|
||||||
|
|
@ -712,7 +654,7 @@ IN_PROCESS_APPLICATION::RunDotnetApplication(DWORD argc, CONST PCWSTR* argv, hos
|
||||||
REQUESTHANDLER_CONFIG*
|
REQUESTHANDLER_CONFIG*
|
||||||
IN_PROCESS_APPLICATION::QueryConfig() const
|
IN_PROCESS_APPLICATION::QueryConfig() const
|
||||||
{
|
{
|
||||||
return m_pConfig;
|
return m_pConfig.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "precomp.hxx"
|
#include "precomp.hxx"
|
||||||
#include "application.h"
|
#include "InProcessApplicationBase.h"
|
||||||
#include "inprocesshandler.h"
|
#include "inprocesshandler.h"
|
||||||
#include "requesthandler_config.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 REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_REQUEST_HANDLER) (IN_PROCESS_HANDLER* pInProcessHandler, void* pvRequestHandlerContext);
|
||||||
typedef BOOL(WINAPI * PFN_SHUTDOWN_HANDLER) (void* pvShutdownHandlerContext);
|
typedef BOOL(WINAPI * PFN_SHUTDOWN_HANDLER) (void* pvShutdownHandlerContext);
|
||||||
typedef REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_MANAGED_CONTEXT_HANDLER)(void *pvManagedHttpContext, HRESULT hrCompletionStatus, DWORD cbCompletion);
|
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:
|
public:
|
||||||
IN_PROCESS_APPLICATION(
|
IN_PROCESS_APPLICATION(
|
||||||
IHttpServer* pHttpServer,
|
IHttpServer* pHttpServer,
|
||||||
REQUESTHANDLER_CONFIG *pConfig);
|
std::unique_ptr<REQUESTHANDLER_CONFIG> pConfig);
|
||||||
|
|
||||||
~IN_PROCESS_APPLICATION();
|
~IN_PROCESS_APPLICATION();
|
||||||
|
|
||||||
|
|
@ -36,12 +35,6 @@ public:
|
||||||
_In_ VOID* pvShutdownHandlerContext
|
_In_ VOID* pvShutdownHandlerContext
|
||||||
);
|
);
|
||||||
|
|
||||||
__override
|
|
||||||
VOID
|
|
||||||
Recycle(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
__override
|
__override
|
||||||
HRESULT
|
HRESULT
|
||||||
CreateHandler(
|
CreateHandler(
|
||||||
|
|
@ -163,7 +156,6 @@ private:
|
||||||
BOOL m_fRecycleCalled;
|
BOOL m_fRecycleCalled;
|
||||||
BOOL m_fInitialized;
|
BOOL m_fInitialized;
|
||||||
|
|
||||||
SRWLOCK m_srwLock;
|
|
||||||
|
|
||||||
// Thread for capturing startup stderr logs when logging is disabled
|
// Thread for capturing startup stderr logs when logging is disabled
|
||||||
HANDLE m_hErrThread;
|
HANDLE m_hErrThread;
|
||||||
|
|
@ -172,11 +164,9 @@ private:
|
||||||
static IN_PROCESS_APPLICATION* s_Application;
|
static IN_PROCESS_APPLICATION* s_Application;
|
||||||
|
|
||||||
IOutputManager* m_pLoggerProvider;
|
IOutputManager* m_pLoggerProvider;
|
||||||
REQUESTHANDLER_CONFIG* m_pConfig;
|
std::unique_ptr<REQUESTHANDLER_CONFIG> m_pConfig;
|
||||||
|
|
||||||
|
|
||||||
// Allows to override call to hostfxr_main with custome callback
|
|
||||||
// used in testing
|
|
||||||
static hostfxr_main_fn s_fMainCallback;
|
|
||||||
|
|
||||||
static
|
static
|
||||||
VOID
|
VOID
|
||||||
|
|
|
||||||
|
|
@ -23,28 +23,6 @@ __override
|
||||||
REQUEST_NOTIFICATION_STATUS
|
REQUEST_NOTIFICATION_STATUS
|
||||||
IN_PROCESS_HANDLER::OnExecuteRequestHandler()
|
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
|
// FREB log
|
||||||
|
|
||||||
if (ANCMEvents::ANCM_START_APPLICATION_SUCCESS::IsEnabled(m_pW3Context->GetTraceContext()))
|
if (ANCMEvents::ANCM_START_APPLICATION_SUCCESS::IsEnabled(m_pW3Context->GetTraceContext()))
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,8 @@ enum APP_HOSTING_MODEL
|
||||||
class REQUESTHANDLER_CONFIG
|
class REQUESTHANDLER_CONFIG
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
~REQUESTHANDLER_CONFIG();
|
~REQUESTHANDLER_CONFIG();
|
||||||
|
|
||||||
static
|
static
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\;</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\;</AdditionalLibraryDirectories>
|
||||||
<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;%(AdditionalDependencies)</AdditionalDependencies>
|
<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)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>
|
<AdditionalDependencies>
|
||||||
|
|
@ -127,7 +127,7 @@
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\;</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\;</AdditionalLibraryDirectories>
|
||||||
<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;%(AdditionalDependencies)</AdditionalDependencies>
|
<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)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>
|
<AdditionalDependencies>
|
||||||
|
|
@ -153,7 +153,7 @@
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\;</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\;</AdditionalLibraryDirectories>
|
||||||
<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;%(AdditionalDependencies)</AdditionalDependencies>
|
<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)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>
|
<AdditionalDependencies>
|
||||||
|
|
@ -179,7 +179,7 @@
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\;</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\;</AdditionalLibraryDirectories>
|
||||||
<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;%(AdditionalDependencies)</AdditionalDependencies>
|
<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)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>
|
<AdditionalDependencies>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ namespace InprocessTests
|
||||||
{
|
{
|
||||||
auto server = new MockHttpServer();
|
auto server = new MockHttpServer();
|
||||||
auto requestHandlerConfig = MockRequestHandlerConfig::CreateConfig();
|
auto requestHandlerConfig = MockRequestHandlerConfig::CreateConfig();
|
||||||
IN_PROCESS_APPLICATION *app = new IN_PROCESS_APPLICATION(server, requestHandlerConfig);
|
auto config = std::unique_ptr<REQUESTHANDLER_CONFIG>(requestHandlerConfig);
|
||||||
|
IN_PROCESS_APPLICATION *app = new IN_PROCESS_APPLICATION(server, std::move(config));
|
||||||
{
|
{
|
||||||
std::wstring exePath(L"hello");
|
std::wstring exePath(L"hello");
|
||||||
app->SetParameter(L"InProcessExeLocation", exePath.c_str());
|
app->SetParameter(L"InProcessExeLocation", exePath.c_str());
|
||||||
|
|
@ -24,5 +25,3 @@ namespace InprocessTests
|
||||||
ASSERT_STREQ(app->QueryExeLocation(), L"hello");
|
ASSERT_STREQ(app->QueryExeLocation(), L"hello");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using IISIntegration.FunctionalTests.Utilities;
|
using IISIntegration.FunctionalTests.Utilities;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
{
|
{
|
||||||
|
|
@ -18,7 +18,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
public async Task CheckStdoutWithRandomNumber(string path)
|
public async Task CheckStdoutWithRandomNumber(string path)
|
||||||
{
|
{
|
||||||
var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite");
|
var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite");
|
||||||
deploymentParameters.PublishApplicationBeforeDeployment = true;
|
|
||||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path;
|
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path;
|
||||||
var randomNumberString = new Random(Guid.NewGuid().GetHashCode()).Next(10000000).ToString();
|
var randomNumberString = new Random(Guid.NewGuid().GetHashCode()).Next(10000000).ToString();
|
||||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_RANDOM_VALUE"] = randomNumberString;
|
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_RANDOM_VALUE"] = randomNumberString;
|
||||||
|
|
@ -42,8 +41,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
public async Task CheckStdoutWithLargeWrites(string path)
|
public async Task CheckStdoutWithLargeWrites(string path)
|
||||||
{
|
{
|
||||||
var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite");
|
var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite");
|
||||||
deploymentParameters.PublishApplicationBeforeDeployment = true;
|
|
||||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path;
|
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path;
|
||||||
|
|
||||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
||||||
var response = await deploymentResult.RetryingHttpClient.GetAsync(path);
|
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)));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
var deploymentParameters = new DeploymentParameters(variant)
|
var deploymentParameters = new DeploymentParameters(variant)
|
||||||
{
|
{
|
||||||
ApplicationPath = Helpers.GetInProcessTestSitesPath(),
|
ApplicationPath = Helpers.GetInProcessTestSitesPath(),
|
||||||
PublishApplicationBeforeDeployment = true,
|
PublishApplicationBeforeDeployment = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<Import Project="..\..\..\build\testsite.props" />
|
<Import Project="..\..\..\build\testsite.props" />
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue