support shutdown timeout for inprocess application (#703)

This commit is contained in:
pan-wang 2018-03-21 13:37:26 -07:00 committed by GitHub
parent 5baa53393f
commit ffeebfc8b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 5 deletions

View File

@ -21,6 +21,7 @@
#define ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG L"Warning: Could not create stdoutLogFile %s, ErrorCode = '0x%x'."
#define ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE_MSG L"Failed to gracefully shutdown process '%d'."
#define ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST_MSG L"Sent shutdown HTTP message to process '%d' and received http status '%d'."
#define ASPNETCORE_EVENT_APP_SHUTDOWN_FAILURE_MSG L"Failed to gracefully shutdown application '%s'."
#define ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG L"Application '%s' with physical root '%s' failed to load clr and managed application, ErrorCode = '0x%x."
#define ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG L"Only one inprocess application is allowed per IIS application pool. Please assign the application '%s' to a different IIS application pool."
#define ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG L"Mixed hosting model is not supported. Application '%s' configured with different hostingModel value '%d' other than the one of running application(s)."

View File

@ -40,9 +40,90 @@ IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
s_Application = NULL;
}
//static
VOID
IN_PROCESS_APPLICATION::DoShutDown(
LPVOID lpParam
)
{
IN_PROCESS_APPLICATION* pApplication = static_cast<IN_PROCESS_APPLICATION*>(lpParam);
DBG_ASSERT(pApplication);
pApplication->ShutDownInternal();
}
__override
VOID
IN_PROCESS_APPLICATION::ShutDown()
IN_PROCESS_APPLICATION::ShutDown(
VOID
)
{
HANDLE hThread = NULL;
HRESULT hr = S_OK;
DWORD dwThreadStatus = 0;
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
if (IsDebuggerPresent())
{
dwTimeout = INFINITE;
}
hThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)DoShutDown,
this, // thread function arguments
0, // default creation flags
NULL); // receive thread identifier
if (hThread == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Finished;
}
if (WaitForSingleObject(hThread, dwTimeout) != WAIT_OBJECT_0)
{
// 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)
{
// Calling back into managed at this point is prone to have AVs
// Calling terminate thread here may be our best solution.
TerminateThread(hThread, STATUS_CONTROL_C_EXIT);
hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
}
}
Finished:
if (hThread != NULL)
{
CloseHandle(hThread);
}
m_hThread = NULL;
if (FAILED(hr))
{
STACK_STRU(strEventMsg, 256);
//
// Assumption: inprocess application shutdown will be called only at process shutdown
// Based on this assumption, we just let shutdown continue and process will exit
// Log a warning for ungraceful shutdown
//
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
ASPNETCORE_EVENT_APP_SHUTDOWN_FAILURE_MSG,
m_pConfig->QueryConfigPath()->QueryStr())))
{
UTILITY::LogEvent(g_hEventLog,
EVENTLOG_WARNING_TYPE,
ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE,
strEventMsg.QueryStr());
}
}
}
VOID
IN_PROCESS_APPLICATION::ShutDownInternal()
{
DWORD dwThreadStatus = 0;
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
@ -54,10 +135,6 @@ IN_PROCESS_APPLICATION::ShutDown()
{
dwTimeout = INFINITE;
}
else
{
dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
}
if (m_fShutdownCalledFromNative ||
m_status == APPLICATION_STATUS::STARTING ||

View File

@ -99,6 +99,17 @@ public:
}
private:
static
VOID
DoShutDown(
LPVOID lpParam
);
VOID
ShutDownInternal(
VOID
);
// Thread executing the .NET Core process
HANDLE m_hThread;