fixing graceful shutdown on Win7 and IISExpress

This commit is contained in:
pan-wang 2017-01-23 15:33:17 -08:00
parent 66b98a1c04
commit 044648a213
2 changed files with 494 additions and 478 deletions

View File

@ -219,7 +219,7 @@ private:
STRU m_struFullLogFile; STRU m_struFullLogFile;
STTIMER m_Timer; STTIMER m_Timer;
HANDLE m_hStdoutHandle; HANDLE m_hStdoutHandle;
volatile BOOL m_fStopping; volatile LONG m_lStopping;
volatile BOOL m_fReady; volatile BOOL m_fReady;
CRITICAL_SECTION m_csLock; CRITICAL_SECTION m_csLock;
SOCKET m_socket; SOCKET m_socket;

View File

@ -469,8 +469,8 @@ SERVER_PROCESS::StartProcess(
dwCreationFlags = CREATE_NO_WINDOW | dwCreationFlags = CREATE_NO_WINDOW |
CREATE_UNICODE_ENVIRONMENT | CREATE_UNICODE_ENVIRONMENT |
CREATE_SUSPENDED; // | CREATE_SUSPENDED |
//CREATE_NEW_PROCESS_GROUP; CREATE_NEW_PROCESS_GROUP;
finalCommandLine.Copy(pszCommandLine); finalCommandLine.Copy(pszCommandLine);
@ -1221,25 +1221,36 @@ SERVER_PROCESS::SendSignal(
{ {
HANDLE hProc = INVALID_HANDLE_VALUE; HANDLE hProc = INVALID_HANDLE_VALUE;
BOOL fIsSuccess = FALSE; BOOL fIsSuccess = FALSE;
BOOL fFreeConsole = FALSE;
LPCWSTR apsz[1]; LPCWSTR apsz[1];
STACK_STRU(strEventMsg, 256); STACK_STRU(strEventMsg, 256);
ReferenceServerProcess();
hProc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, m_dwProcessId); hProc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, m_dwProcessId);
if (hProc != INVALID_HANDLE_VALUE) if (hProc != INVALID_HANDLE_VALUE)
{ {
fIsSuccess = GenerateConsoleCtrlEvent(CTRL_C_EVENT, m_dwProcessId); // free current console first, as we migh have one, e.g., hostedwebcore case
fFreeConsole = FreeConsole();
if (!fIsSuccess)
{
if (AttachConsole(m_dwProcessId)) if (AttachConsole(m_dwProcessId))
{ {
fIsSuccess = GenerateConsoleCtrlEvent(CTRL_C_EVENT, m_dwProcessId); // call ctrl-break instead of ctrl-c as child process may ignore ctrl-c
fIsSuccess = GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, m_dwProcessId);
FreeConsole(); FreeConsole();
} }
if (fFreeConsole)
{
// IISExpress and hostedwebcore w3wp run as background process
// have to attach console back to ensure post app_offline scenario still work
AttachConsole(ATTACH_PARENT_PROCESS);
} }
} }
if (!fIsSuccess || (WaitForSingleObject(hProc, m_dwShutdownTimeLimitInMS) != WAIT_OBJECT_0)) if (!fIsSuccess || (WaitForSingleObject(hProc, m_dwShutdownTimeLimitInMS) != WAIT_OBJECT_0))
{
if (InterlockedCompareExchange(&m_lStopping, 1L, 0L) == 0L)
{ {
//Backend process will be terminated, remove the waitcallback //Backend process will be terminated, remove the waitcallback
if (m_hProcessWaitHandle != NULL) if (m_hProcessWaitHandle != NULL)
@ -1251,6 +1262,10 @@ SERVER_PROCESS::SendSignal(
// cannot gracefully shutdown or timeout, terminate the process // cannot gracefully shutdown or timeout, terminate the process
TerminateProcess(m_hProcessHandle, 0); TerminateProcess(m_hProcessHandle, 0);
// as we skipped process exit callback (ProcessHandleCallback),
// need to dereference the object otherwise memory leak
DereferenceServerProcess();
// log a warning for ungraceful shutdown // log a warning for ungraceful shutdown
if (SUCCEEDED(strEventMsg.SafeSnwprintf( if (SUCCEEDED(strEventMsg.SafeSnwprintf(
ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE_MSG, ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE_MSG,
@ -1271,6 +1286,7 @@ SERVER_PROCESS::SendSignal(
} }
} }
} }
}
if (hProc != INVALID_HANDLE_VALUE) if (hProc != INVALID_HANDLE_VALUE)
{ {
@ -1282,6 +1298,8 @@ SERVER_PROCESS::SendSignal(
CloseHandle(m_hProcessHandle); CloseHandle(m_hProcessHandle);
m_hProcessHandle = INVALID_HANDLE_VALUE; m_hProcessHandle = INVALID_HANDLE_VALUE;
} }
DereferenceServerProcess();
} }
// //
@ -1655,7 +1673,7 @@ SERVER_PROCESS::SERVER_PROCESS() :
m_cChildProcess(0), m_cChildProcess(0),
m_socket(INVALID_SOCKET), m_socket(INVALID_SOCKET),
m_fReady(FALSE), m_fReady(FALSE),
m_fStopping( FALSE ), m_lStopping(0L),
m_hStdoutHandle(NULL), m_hStdoutHandle(NULL),
m_fStdoutLogEnabled(FALSE), m_fStdoutLogEnabled(FALSE),
m_hJobObject(NULL), m_hJobObject(NULL),
@ -1826,19 +1844,17 @@ SERVER_PROCESS::HandleProcessExit()
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
BOOL fReady = FALSE; BOOL fReady = FALSE;
if (InterlockedCompareExchange(&m_lStopping, 1L, 0L) == 0L)
{
CheckIfServerIsUp(m_dwPort, &fReady); CheckIfServerIsUp(m_dwPort, &fReady);
if (!fReady) if (!fReady)
{ {
if( !m_fStopping )
{
m_fStopping = TRUE;
m_pProcessManager->ShutdownProcess(this); m_pProcessManager->ShutdownProcess(this);
} }
}
DereferenceServerProcess(); DereferenceServerProcess();
}
return hr; return hr;
} }