* fix the AV in recycle process. this is due to we call Recycle again when the background thread exists * more fixes * reset hosting mode when all applications got removed
This commit is contained in:
parent
02cffd16ec
commit
448a2afed8
|
|
@ -3,7 +3,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AspNetCoreModuleVersionMajor>7</AspNetCoreModuleVersionMajor>
|
<AspNetCoreModuleVersionMajor>7</AspNetCoreModuleVersionMajor>
|
||||||
<AspNetCoreModuleVersionMinor>1</AspNetCoreModuleVersionMinor>
|
<AspNetCoreModuleVersionMinor>1</AspNetCoreModuleVersionMinor>
|
||||||
<AspNetCoreModuleVersionPatch>1968</AspNetCoreModuleVersionPatch>
|
<AspNetCoreModuleVersionPatch>1987</AspNetCoreModuleVersionPatch>
|
||||||
<AspNetCoreModuleVersionSuffix>-RTM</AspNetCoreModuleVersionSuffix>
|
<AspNetCoreModuleVersionSuffix>-RTM</AspNetCoreModuleVersionSuffix>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ private:
|
||||||
|
|
||||||
BOOL m_fManagedAppLoaded;
|
BOOL m_fManagedAppLoaded;
|
||||||
BOOL m_fLoadManagedAppError;
|
BOOL m_fLoadManagedAppError;
|
||||||
|
BOOL m_fInitialized;
|
||||||
BOOL m_fIsWebSocketsConnection;
|
BOOL m_fIsWebSocketsConnection;
|
||||||
|
|
||||||
static IN_PROCESS_APPLICATION* s_Application;
|
static IN_PROCESS_APPLICATION* s_Application;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG L"Maximum rapid fail count per minute of '%d' exceeded."
|
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG L"Maximum rapid fail count per minute of '%d' exceeded."
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG L"Application '%s' failed to parse processPath and arguments due to internal error, ErrorCode = '0x%x'."
|
#define ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG L"Application '%s' failed to parse processPath and arguments due to internal error, ErrorCode = '0x%x'."
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s'but failed to get its status, ErrorCode = '0x%x'."
|
#define ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s'but failed to get its status, ErrorCode = '0x%x'."
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s', ErrorCode = '0x%x : %x."
|
#define ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s', ErrorCode = '0x%x' processStatus code '%x'."
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_WRONGPORT_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but failed to listen on the given port '%d'"
|
#define ASPNETCORE_EVENT_PROCESS_START_WRONGPORT_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but failed to listen on the given port '%d'"
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but either crashed or did not reponse or did not listen on the given port '%d', ErrorCode = '0x%x'"
|
#define ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but either crashed or did not reponse or did not listen on the given port '%d', ErrorCode = '0x%x'"
|
||||||
#define ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG L"Warning: Could not create stdoutLogFile %s, ErrorCode = %d."
|
#define ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG L"Warning: Could not create stdoutLogFile %s, ErrorCode = %d."
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,10 @@ APPLICATION_MANAGER::RecycleApplication(
|
||||||
}
|
}
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
AcquireSRWLockExclusive(&m_srwLock);
|
||||||
m_pApplicationHash->DeleteKey(&key);
|
m_pApplicationHash->DeleteKey(&key);
|
||||||
|
if (m_pApplicationHash->Count() == 0)
|
||||||
|
{
|
||||||
|
m_hostingModel = HOSTING_UNKNOWN;
|
||||||
|
}
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
ReleaseSRWLockExclusive(&m_srwLock);
|
||||||
|
|
||||||
Finished:
|
Finished:
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,26 @@
|
||||||
|
|
||||||
ASPNETCORE_CONFIG::~ASPNETCORE_CONFIG()
|
ASPNETCORE_CONFIG::~ASPNETCORE_CONFIG()
|
||||||
{
|
{
|
||||||
if (QueryHostingModel() == HOSTING_IN_PROCESS &&
|
if (QueryHostingModel() == HOSTING_IN_PROCESS &&
|
||||||
!g_fRecycleProcessCalled &&
|
!g_fRecycleProcessCalled &&
|
||||||
!g_pHttpServer->IsCommandLineLaunch())
|
(g_pHttpServer->GetAdminManager() != NULL))
|
||||||
{
|
{
|
||||||
|
// There is a bug in IHttpServer::RecycleProcess. It will hit AV when worker process
|
||||||
|
// has already been in recycling state.
|
||||||
|
// To workaround, do null check on GetAdminManager(). If it is NULL, worker process is in recycling
|
||||||
|
// Do not call RecycleProcess again
|
||||||
|
|
||||||
// RecycleProcess can olny be called once
|
// RecycleProcess can olny be called once
|
||||||
// In case of configuration change for in-process app
|
// In case of configuration change for in-process app
|
||||||
// We want notify IIS first to let new request routed to new worker process
|
// We want notify IIS first to let new request routed to new worker process
|
||||||
g_fRecycleProcessCalled = TRUE;
|
|
||||||
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Configuration Change");
|
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Configuration Change");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It's safe for us to set this g_fRecycleProcessCalled
|
||||||
|
// as in_process scenario will always recycle the worker process for configuration change
|
||||||
|
g_fRecycleProcessCalled = TRUE;
|
||||||
|
|
||||||
m_struApplicationFullPath.Reset();
|
m_struApplicationFullPath.Reset();
|
||||||
if (m_pEnvironmentVariables != NULL)
|
if (m_pEnvironmentVariables != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1043,7 +1043,6 @@ FORWARDING_HANDLER::OnExecuteRequestHandler(
|
||||||
IHttpRequest *pRequest = m_pW3Context->GetRequest();
|
IHttpRequest *pRequest = m_pW3Context->GetRequest();
|
||||||
IHttpResponse *pResponse = m_pW3Context->GetResponse();
|
IHttpResponse *pResponse = m_pW3Context->GetResponse();
|
||||||
PROTOCOL_CONFIG *pProtocol = &sm_ProtocolConfig;
|
PROTOCOL_CONFIG *pProtocol = &sm_ProtocolConfig;
|
||||||
APPLICATION_MANAGER *pApplicationManager = NULL;
|
|
||||||
SERVER_PROCESS *pServerProcess = NULL;
|
SERVER_PROCESS *pServerProcess = NULL;
|
||||||
USHORT cchHostName = 0;
|
USHORT cchHostName = 0;
|
||||||
BOOL fSecure = FALSE;
|
BOOL fSecure = FALSE;
|
||||||
|
|
@ -1427,7 +1426,7 @@ Failure:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (SUCCEEDED(pApplicationManager->Get502ErrorPage(&pDataChunk)))
|
if (SUCCEEDED(APPLICATION_MANAGER::GetInstance()->Get502ErrorPage(&pDataChunk)))
|
||||||
{
|
{
|
||||||
if (FAILED(hr = pResponse->WriteEntityChunkByReference(pDataChunk)))
|
if (FAILED(hr = pResponse->WriteEntityChunkByReference(pDataChunk)))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,8 @@ IN_PROCESS_APPLICATION* IN_PROCESS_APPLICATION::s_Application = NULL;
|
||||||
IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION() :
|
IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION() :
|
||||||
m_ProcessExitCode ( 0 ),
|
m_ProcessExitCode ( 0 ),
|
||||||
m_fManagedAppLoaded ( FALSE ),
|
m_fManagedAppLoaded ( FALSE ),
|
||||||
m_fLoadManagedAppError ( FALSE )
|
m_fLoadManagedAppError ( FALSE ),
|
||||||
|
m_fInitialized ( FALSE )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -510,6 +511,7 @@ IN_PROCESS_APPLICATION::Initialize(
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
m_fInitialized = TRUE;
|
||||||
|
|
||||||
Finished:
|
Finished:
|
||||||
return hr;
|
return hr;
|
||||||
|
|
@ -636,50 +638,57 @@ IN_PROCESS_APPLICATION::Recycle(
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DWORD dwThreadStatus = 0;
|
if (m_fInitialized)
|
||||||
DWORD dwTimeout = m_pConfiguration->QueryShutdownTimeLimitInMS();
|
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
|
||||||
|
|
||||||
if (!g_pHttpServer->IsCommandLineLaunch() && !g_fRecycleProcessCalled)
|
|
||||||
{
|
{
|
||||||
// IIS scenario.
|
DWORD dwThreadStatus = 0;
|
||||||
// notify IIS first so that new request will be routed to new worker process
|
DWORD dwTimeout = m_pConfiguration->QueryShutdownTimeLimitInMS();
|
||||||
g_fRecycleProcessCalled = TRUE;
|
|
||||||
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Demand");
|
|
||||||
}
|
|
||||||
// First call into the managed server and shutdown
|
|
||||||
if (m_ShutdownHandler != NULL)
|
|
||||||
{
|
|
||||||
m_ShutdownHandler(m_ShutdownHandlerContext);
|
|
||||||
m_ShutdownHandler = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_hThread != NULL &&
|
AcquireSRWLockExclusive(&m_srwLock);
|
||||||
GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 &&
|
|
||||||
dwThreadStatus == STILL_ACTIVE)
|
if (!g_pHttpServer->IsCommandLineLaunch() &&
|
||||||
{
|
!g_fRecycleProcessCalled &&
|
||||||
// wait for gracefullshut down, i.e., the exit of the background thread or timeout
|
(g_pHttpServer->GetAdminManager() != NULL))
|
||||||
if (WaitForSingleObject(m_hThread, dwTimeout) != WAIT_OBJECT_0)
|
|
||||||
{
|
{
|
||||||
// if the thread is still running, we need kill it first before exit to avoid AV
|
// IIS scenario.
|
||||||
if (GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
// notify IIS first so that new request will be routed to new worker process
|
||||||
|
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Demand");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_fRecycleProcessCalled = TRUE;
|
||||||
|
|
||||||
|
// First call into the managed server and shutdown
|
||||||
|
if (m_ShutdownHandler != NULL)
|
||||||
|
{
|
||||||
|
m_ShutdownHandler(m_ShutdownHandlerContext);
|
||||||
|
m_ShutdownHandler = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hThread != NULL &&
|
||||||
|
GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 &&
|
||||||
|
dwThreadStatus == STILL_ACTIVE)
|
||||||
|
{
|
||||||
|
// wait for gracefullshut down, i.e., the exit of the background thread or timeout
|
||||||
|
if (WaitForSingleObject(m_hThread, dwTimeout) != WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
TerminateThread(m_hThread, STATUS_CONTROL_C_EXIT);
|
// if the thread is still running, we need kill it first before exit to avoid AV
|
||||||
|
if (GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
||||||
|
{
|
||||||
|
TerminateThread(m_hThread, STATUS_CONTROL_C_EXIT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(m_hThread);
|
CloseHandle(m_hThread);
|
||||||
m_hThread = NULL;
|
m_hThread = NULL;
|
||||||
s_Application = NULL;
|
s_Application = NULL;
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
|
|
||||||
if (g_pHttpServer->IsCommandLineLaunch())
|
ReleaseSRWLockExclusive(&m_srwLock);
|
||||||
{
|
if (g_pHttpServer && g_pHttpServer->IsCommandLineLaunch())
|
||||||
// IISExpress scenario
|
{
|
||||||
// Can only call exit to terminate current process
|
// IISExpress scenario
|
||||||
exit(0);
|
// Can only call exit to terminate current process
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue