support shutdown timeout for inprocess application (#703)
This commit is contained in:
parent
5baa53393f
commit
ffeebfc8b9
|
|
@ -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_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_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_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_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_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)."
|
#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)."
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,90 @@ IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
|
||||||
s_Application = NULL;
|
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
|
__override
|
||||||
VOID
|
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 dwThreadStatus = 0;
|
||||||
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
||||||
|
|
@ -54,10 +135,6 @@ IN_PROCESS_APPLICATION::ShutDown()
|
||||||
{
|
{
|
||||||
dwTimeout = INFINITE;
|
dwTimeout = INFINITE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_fShutdownCalledFromNative ||
|
if (m_fShutdownCalledFromNative ||
|
||||||
m_status == APPLICATION_STATUS::STARTING ||
|
m_status == APPLICATION_STATUS::STARTING ||
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
DoShutDown(
|
||||||
|
LPVOID lpParam
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ShutDownInternal(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
// Thread executing the .NET Core process
|
// Thread executing the .NET Core process
|
||||||
HANDLE m_hThread;
|
HANDLE m_hThread;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue