Fixing couple issues (#763)

adding more logs and fix memory leak in case of configuration change and then shutdown
This commit is contained in:
pan-wang 2018-04-12 14:10:25 -07:00 committed by GitHub
parent 5c34364d73
commit 9c83280770
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 118 additions and 408 deletions

View File

@ -22,9 +22,7 @@ public:
if ( _pTimer )
{
CancelTimer();
CloseThreadpoolTimer( _pTimer );
_pTimer = NULL;
}
}
@ -107,9 +105,10 @@ public:
// have completed.
//
if (_pTimer != NULL)
WaitForThreadpoolTimerCallbacks( _pTimer, TRUE );
{
WaitForThreadpoolTimerCallbacks(_pTimer, TRUE);
}
_pTimer = NULL;
fInCanel = FALSE;
}

View File

@ -79,18 +79,18 @@ public:
~APPLICATION_MANAGER()
{
if (m_pFileWatcher != NULL)
{
delete m_pFileWatcher;
m_pFileWatcher = NULL;
}
if(m_pApplicationInfoHash != NULL)
{
m_pApplicationInfoHash->Clear();
delete m_pApplicationInfoHash;
m_pApplicationInfoHash = NULL;
}
if( m_pFileWatcher!= NULL )
{
delete m_pFileWatcher;
m_pFileWatcher = NULL;
}
}
FILE_WATCHER*

View File

@ -18,6 +18,7 @@ APPLICATION_INFO::~APPLICATION_INFO()
// the entry will delete itself when processing this FCN
m_pFileWatcherEntry->MarkEntryInValid();
m_pFileWatcherEntry->StopMonitor();
m_pFileWatcherEntry->DereferenceFileWatcherEntry();
m_pFileWatcherEntry = NULL;
}
@ -587,6 +588,11 @@ APPLICATION_INFO::RecycleApplication()
g_pHttpServer->RecycleProcess(L"On Demand by AspNetCore Module for recycle application failure");
}
}
else
{
// Closing a thread handle does not terminate the associated thread or remove the thread object.
CloseHandle(hThread);
}
if (fLockAcquired)
{

View File

@ -135,7 +135,6 @@ Win32 error
INFINITE);
DBG_ASSERT(fSuccess);
DebugPrint(1, "FILE_WATCHER::ChangeNotificationThread");
dwErrorStatus = fSuccess ? ERROR_SUCCESS : GetLastError();
if (completionKey == FILE_WATCHER_SHUTDOWN_KEY)
@ -186,7 +185,7 @@ None
{
FILE_WATCHER_ENTRY * pMonitorEntry;
pMonitorEntry = CONTAINING_RECORD(pOverlapped, FILE_WATCHER_ENTRY, _overlapped);
pMonitorEntry->DereferenceFileWatcherEntry();
DBG_ASSERT(pMonitorEntry != NULL);
pMonitorEntry->HandleChangeCompletion(dwCompletionStatus, cbCompletion);
@ -198,14 +197,13 @@ None
//
pMonitorEntry->Monitor();
}
else
{
//
// Marked by application distructor
// Deference the entry to delete it
//
pMonitorEntry->DereferenceFileWatcherEntry();
}
//
// Deference the counter not matter whether the monitor is valid
// Valid: Monitor increases the counter, need to reduce one
// InValid: Reduce the counter to free the entry
//
pMonitorEntry->DereferenceFileWatcherEntry();
}
@ -279,9 +277,9 @@ HRESULT
// From documentation it is not clear if that combination
// of return values is specific to closing handles or whether
// it could also mean an error condition. Hence we will maintain
// explicit flag that will help us determine if entry
// is being shutdown (StopMonitor() called)
//
// explicit flag that will help us determine if entry
// is being shutdown (StopMonitor() called)
//
if (_lStopMonitorCalled)
{
goto Finished;
@ -364,6 +362,7 @@ FILE_WATCHER_ENTRY::Monitor(VOID)
NULL))
{
hr = HRESULT_FROM_WIN32(GetLastError());
DereferenceFileWatcherEntry();
}
ReleaseSRWLockExclusive(&_srwLock);
@ -380,15 +379,17 @@ FILE_WATCHER_ENTRY::StopMonitor(VOID)
//
InterlockedExchange(&_lStopMonitorCalled, 1);
AcquireSRWLockExclusive(&_srwLock);
if (_hDirectory != INVALID_HANDLE_VALUE)
{
CloseHandle(_hDirectory);
_hDirectory = INVALID_HANDLE_VALUE;
AcquireSRWLockExclusive(&_srwLock);
if (_hDirectory != INVALID_HANDLE_VALUE)
{
CloseHandle(_hDirectory);
_hDirectory = INVALID_HANDLE_VALUE;
DereferenceFileWatcherEntry();
}
ReleaseSRWLockExclusive(&_srwLock);
}
ReleaseSRWLockExclusive(&_srwLock);
}
HRESULT

View File

@ -1,328 +0,0 @@
/*++
Copyright (c) .NET Foundation. All rights reserved.
Licensed under the MIT License. See License.txt in the project root for license information.
Module Name:
aspnetcore_msg.mc
Abstract:
Asp.Net Core Module localizable messages.
--*/
#ifndef _ASPNETCORE_MSG_H_
#define _ASPNETCORE_MSG_H_
//
// Values are 32 bit values laid out as follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
//
// where
//
// Sev - is the severity code
//
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
//
// C - is the Customer code flag
//
// R - is a reserved bit
//
// Facility - is the facility code
//
// Code - is the facility's status code
//
//
// Define the facility codes
//
//
// Define the severity codes
//
//
// MessageId: ASPNETCORE_EVENT_PROCESS_START_ERROR
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_PROCESS_START_ERROR ((DWORD)0x000003E8L)
//
// MessageId: ASPNETCORE_EVENT_PROCESS_START_SUCCESS
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS ((DWORD)0x000003E9L)
//
// MessageId: ASPNETCORE_EVENT_PROCESS_CRASH
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_PROCESS_CRASH ((DWORD)0x000003EAL)
//
// MessageId: ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED ((DWORD)0x000003EBL)
//
// MessageId: ASPNETCORE_EVENT_CONFIG_ERROR
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_CONFIG_ERROR ((DWORD)0x000003ECL)
//
// MessageId: ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE ((DWORD)0x000003EDL)
//
// MessageId: ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST ((DWORD)0x000003EEL)
//
// MessageId: ASPNETCORE_EVENT_LOAD_CLR_FALIURE
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_LOAD_CLR_FALIURE ((DWORD)0x000003EFL)
//
// MessageId: ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP ((DWORD)0x000003F0L)
//
// MessageId: ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR ((DWORD)0x000003F1L)
//
// MessageId: ASPNETCORE_EVENT_ADD_APPLICATION_ERROR
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_ADD_APPLICATION_ERROR ((DWORD)0x000003F2L)
//
// MessageId: ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT ((DWORD)0x000003F3L)
//
// MessageId: ASPNETCORE_EVENT_RECYCLE_APPOFFLINE
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_RECYCLE_APPOFFLINE ((DWORD)0x000003F4L)
//
// MessageId: ASPNETCORE_EVENT_MODULE_DISABLED
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_MODULE_DISABLED ((DWORD)0x000003F5L)
//
// MessageId: ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP ((DWORD)0x000003F6L)
//
// MessageId: ASPNETCORE_EVENT_PORTABLE_APP_DOTNET_MISSING
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_PORTABLE_APP_DOTNET_MISSING ((DWORD)0x000003F7L)
//
// MessageId: ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND ((DWORD)0x000003F8L)
//
// MessageId: ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND ((DWORD)0x000003F9L)
//
// MessageId: ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION ((DWORD)0x000003FAL)
//
// MessageId: ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND ((DWORD)0x000003FBL)
//
// MessageId: ASPNETCORE_EVENT_PROCESS_START_FAILURE
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_PROCESS_START_FAILURE ((DWORD)0x000003FCL)
//
// MessageId: ASPNETCORE_EVENT_RECYCLE_CONFIGURATION
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_RECYCLE_CONFIGURATION ((DWORD)0x000003FDL)
//
// MessageId: ASPNETCORE_EVENT_RECYCLE_APP_FAILURE
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_RECYCLE_APP_FAILURE ((DWORD)0x000003FEL)
//
// MessageId: ASPNETCORE_EVENT_APP_IN_SHUTDOWN
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_APP_IN_SHUTDOWN ((DWORD)0x000003FFL)
//
// MessageId: ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_REMOVED
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_REMOVED ((DWORD)0x00000400L)
//
// MessageId: ASPNETCORE_EVENT_GENERAL_INFO_MSG
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_GENERAL_INFO_MSG ((DWORD)0x00000401L)
//
// MessageId: ASPNETCORE_EVENT_GENERAL_WARNING_MSG
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_GENERAL_WARNING_MSG ((DWORD)0x00000402L)
//
// MessageId: ASPNETCORE_EVENT_GENERAL_ERROR_MSG
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_GENERAL_ERROR_MSG ((DWORD)0x00000403L)
//
// MessageId: ASPNETCORE_EVENT_INPROCESS_RH_MISSING
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_INPROCESS_RH_MISSING ((DWORD)0x00000404L)
//
// MessageId: ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING
//
// MessageText:
//
// %1
//
#define ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING ((DWORD)0x00000405L)
#endif // _ASPNETCORE_MODULE_MSG_H_

View File

@ -206,6 +206,12 @@ Language=English
%1
.
Messageid=1030
SymbolicName=ASPNETCORE_EVENT_PROCESS_SHUTDOWN
Language=English
%1
.
;
;#endif // _ASPNETCORE_MODULE_MSG_H_
;

View File

@ -10,14 +10,15 @@
#define ASPNETCORE_IISEXPRESS_EVENT_PROVIDER L"IIS Express AspNetCore Module"
#define ASPNETCORE_EVENT_MSG_BUFFER_SIZE 256
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG L"Application '%s' started process '%d' successfully and is listening on port '%d'."
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG L"Application '%s' started process '%d' successfully and process '%d' is listening on port '%d'."
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG L"Maximum rapid fail count per minute of '%d' exceeded."
#define ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' at stage '%s', ErrorCode = '0x%x', assigned port %d, retryCounter '%d'."
#define ASPNETCORE_EVENT_PROCESS_START_FAILURE_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' with multiple retries. The last try of listening port is '%d'. See pervious warnings for details."
#define ASPNETCORE_EVENT_PROCESS_START_STATUS_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' , ErrorCode = '0x%x', processStatus '%d'."
#define ASPNETCORE_EVENT_PROCESS_START_STATUS_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' , ErrorCode = '0x%x', processId '%d', processStatus '%d'."
#define ASPNETCORE_EVENT_PROCESS_START_PORTSETUP_ERROR_MSG L"Application '%s' with physical root '%s' failed to choose listen port '%d' given port rang '%d - %d', EorrorCode = '0x%x'. If environment variable 'ASPNETCORE_PORT' was set, try removing it such that a random port is selected instead."
#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 respond or did not listen on the given port '%d', ErrorCode = '0x%x'"
#define ASPNETCORE_EVENT_PROCESS_SHUTDOWN_MSG L"Application '%s' with physical root '%s' shut down process with Id '%d' listening on port '%d'"
#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'."

View File

@ -642,7 +642,7 @@ UTILITY::LogEventF(
STACK_STRU ( strEventMsg, 256 );
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
if (SUCCEEDED(strEventMsg.SafeVsnwprintf(
pstrMsg,
argsList)))
{

View File

@ -523,15 +523,20 @@ SERVER_PROCESS::PostStartCheck(
// make sure the process is still running
if (processStatus != STILL_ACTIVE)
{
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
strEventMsg.SafeSnwprintf(
ASPNETCORE_EVENT_PROCESS_START_STATUS_ERROR_MSG,
m_struAppFullPath.QueryStr(),
m_struPhysicalPath.QueryStr(),
m_struCommandLine.QueryStr(),
hr,
processStatus);
goto Finished;
// double check
if (GetExitCodeProcess(m_hProcessHandle, &processStatus) && processStatus != STILL_ACTIVE)
{
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
strEventMsg.SafeSnwprintf(
ASPNETCORE_EVENT_PROCESS_START_STATUS_ERROR_MSG,
m_struAppFullPath.QueryStr(),
m_struPhysicalPath.QueryStr(),
m_struCommandLine.QueryStr(),
hr,
m_dwProcessId,
processStatus);
goto Finished;
}
}
}
//
@ -552,6 +557,7 @@ SERVER_PROCESS::PostStartCheck(
if (!fReady)
{
hr = E_APPLICATION_ACTIVATION_TIMED_OUT;
goto Finished;
}
// register call back with the created process
@ -569,6 +575,7 @@ SERVER_PROCESS::PostStartCheck(
// some error occurred - assume debugger is not attached;
fDebuggerAttached = FALSE;
}
if (!g_fNsiApiNotSupported)
{
//
@ -720,11 +727,14 @@ Finished:
m_pForwarderConnection = NULL;
}
UTILITY::LogEvent(
g_hEventLog,
EVENTLOG_WARNING_TYPE,
ASPNETCORE_EVENT_PROCESS_START_ERROR,
strEventMsg.QueryStr());
if (!strEventMsg.IsEmpty())
{
UTILITY::LogEvent(
g_hEventLog,
EVENTLOG_WARNING_TYPE,
ASPNETCORE_EVENT_PROCESS_START_ERROR,
strEventMsg.QueryStr());
}
}
return hr;
}
@ -890,6 +900,7 @@ SERVER_PROCESS::StartProcess(
ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG,
m_struAppFullPath.QueryStr(),
m_dwProcessId,
m_dwListeningProcessId,
m_dwPort);
goto Finished;
@ -1104,10 +1115,10 @@ SERVER_PROCESS::CheckIfServerIsUp(
)
{
HRESULT hr = S_OK;
DWORD dwResult = 0;
DWORD dwResult = ERROR_INSUFFICIENT_BUFFER;
MIB_TCPTABLE_OWNER_PID *pTCPInfo = NULL;
MIB_TCPROW_OWNER_PID *pOwner = NULL;
DWORD dwSize = 0;
DWORD dwSize = 1000; // Initial size for pTCPInfo buffer
int iResult = 0;
SOCKADDR_IN sockAddr;
SOCKET socketCheck = INVALID_SOCKET;
@ -1123,36 +1134,36 @@ SERVER_PROCESS::CheckIfServerIsUp(
if (!g_fNsiApiNotSupported)
{
dwResult = GetExtendedTcpTable(NULL,
&dwSize,
FALSE,
AF_INET,
TCP_TABLE_OWNER_PID_LISTENER,
0);
if (dwResult != NO_ERROR && dwResult != ERROR_INSUFFICIENT_BUFFER)
while (dwResult == ERROR_INSUFFICIENT_BUFFER)
{
hr = HRESULT_FROM_WIN32(dwResult);
goto Finished;
}
// Increase the buffer size with additional space, MIB_TCPROW 20 bytes
// New entries may be added by other processes before calling GetExtendedTcpTable
dwSize += 200;
pTCPInfo = (MIB_TCPTABLE_OWNER_PID*)HeapAlloc(GetProcessHeap(), 0, dwSize);
if (pTCPInfo == NULL)
{
hr = E_OUTOFMEMORY;
goto Finished;
}
if (pTCPInfo != NULL)
{
HeapFree(GetProcessHeap(), 0, pTCPInfo);
}
dwResult = GetExtendedTcpTable(pTCPInfo,
&dwSize,
FALSE,
AF_INET,
TCP_TABLE_OWNER_PID_LISTENER,
0);
if (dwResult != NO_ERROR)
{
hr = HRESULT_FROM_WIN32(dwResult);
goto Finished;
pTCPInfo = (MIB_TCPTABLE_OWNER_PID*)HeapAlloc(GetProcessHeap(), 0, dwSize);
if (pTCPInfo == NULL)
{
hr = E_OUTOFMEMORY;
goto Finished;
}
dwResult = GetExtendedTcpTable(pTCPInfo,
&dwSize,
FALSE,
AF_INET,
TCP_TABLE_OWNER_PID_LISTENER,
0);
if (dwResult != NO_ERROR && dwResult != ERROR_INSUFFICIENT_BUFFER)
{
hr = HRESULT_FROM_WIN32(dwResult);
goto Finished;
}
}
// iterate pTcpInfo struct to find PID/PORT entry
@ -1199,6 +1210,12 @@ SERVER_PROCESS::CheckIfServerIsUp(
if (iResult == SOCKET_ERROR)
{
hr = HRESULT_FROM_WIN32(WSAGetLastError());
if (hr == HRESULT_FROM_WIN32(WSAECONNREFUSED))
{
// WSAECONNREFUSED means no application listen on the given port.
// This is not a failure. Reset the hresult to S_OK and return fReady to false
hr = S_OK;
}
goto Finished;
}
*pfReady = TRUE;
@ -1860,25 +1877,33 @@ Finished:
return hr;
}
HRESULT
VOID
SERVER_PROCESS::HandleProcessExit( VOID )
{
HRESULT hr = S_OK;
BOOL fReady = FALSE;
DWORD dwProcessId = 0;
if (InterlockedCompareExchange(&m_lStopping, 1L, 0L) == 0L)
{
CheckIfServerIsUp(m_dwPort, &dwProcessId, &fReady);
if (!fReady)
{
UTILITY::LogEventF(
g_hEventLog,
EVENTLOG_INFORMATION_TYPE,
ASPNETCORE_EVENT_PROCESS_SHUTDOWN,
ASPNETCORE_EVENT_PROCESS_SHUTDOWN_MSG,
m_struAppFullPath.QueryStr(),
m_struPhysicalPath.QueryStr(),
m_dwProcessId,
m_dwPort);
m_pProcessManager->ShutdownProcess(this);
}
DereferenceServerProcess();
}
return hr;
}
HRESULT

View File

@ -99,7 +99,7 @@ public:
_In_ BOOL
);
HRESULT
VOID
HandleProcessExit(
VOID
);