Update the filewatcher
Add a reference counter to avoid AV in case web.config was changed
This commit is contained in:
parent
dff0db80ca
commit
f558c5de99
|
|
@ -202,12 +202,6 @@ public:
|
||||||
return m_pAppOfflineHtm;
|
return m_pAppOfflineHtm;
|
||||||
}
|
}
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryApplicationPhysicalPath()
|
|
||||||
{
|
|
||||||
return &m_strAppPhysicalPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
~APPLICATION();
|
~APPLICATION();
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,9 @@ public:
|
||||||
HRESULT
|
HRESULT
|
||||||
GetApplication(
|
GetApplication(
|
||||||
_In_ IHttpContext* pContext,
|
_In_ IHttpContext* pContext,
|
||||||
_In_ LPCWSTR pszApplication,
|
|
||||||
_Out_ APPLICATION ** ppApplication
|
_Out_ APPLICATION ** ppApplication
|
||||||
);
|
);
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
RecycleOnFileChange(
|
|
||||||
APPLICATION_MANAGER* manager,
|
|
||||||
APPLICATION* application
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
RecycleApplication(
|
RecycleApplication(
|
||||||
_In_ LPCWSTR pszApplication
|
_In_ LPCWSTR pszApplication
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define FILE_WATCHER_SHUTDOWN_KEY (ULONG_PTR)(-1)
|
#define FILE_WATCHER_SHUTDOWN_KEY (ULONG_PTR)(-1)
|
||||||
|
#define FILE_WATCHER_ENTRY_BUFFER_SIZE 4096
|
||||||
#ifndef CONTAINING_RECORD
|
#ifndef CONTAINING_RECORD
|
||||||
//
|
//
|
||||||
// Calculate the address of the base of the structure given its type, and an
|
// Calculate the address of the base of the structure given its type, and an
|
||||||
|
|
@ -53,14 +54,12 @@ public:
|
||||||
private:
|
private:
|
||||||
HANDLE m_hCompletionPort;
|
HANDLE m_hCompletionPort;
|
||||||
HANDLE m_hChangeNotificationThread;
|
HANDLE m_hChangeNotificationThread;
|
||||||
CRITICAL_SECTION m_csSyncRoot;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FILE_WATCHER_ENTRY
|
class FILE_WATCHER_ENTRY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FILE_WATCHER_ENTRY(FILE_WATCHER * pFileMonitor);
|
FILE_WATCHER_ENTRY(FILE_WATCHER * pFileMonitor);
|
||||||
virtual ~FILE_WATCHER_ENTRY();
|
|
||||||
|
|
||||||
OVERLAPPED _overlapped;
|
OVERLAPPED _overlapped;
|
||||||
|
|
||||||
|
|
@ -72,6 +71,33 @@ public:
|
||||||
_In_ HANDLE hImpersonationToken
|
_In_ HANDLE hImpersonationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ReferenceFileWatcherEntry() const
|
||||||
|
{
|
||||||
|
InterlockedIncrement(&_cRefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
DereferenceFileWatcherEntry() const
|
||||||
|
{
|
||||||
|
if (InterlockedDecrement(&_cRefs) == 0)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
QueryIsValid() const
|
||||||
|
{
|
||||||
|
return _fIsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MarkEntryInValid()
|
||||||
|
{
|
||||||
|
_fIsValid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT Monitor();
|
HRESULT Monitor();
|
||||||
|
|
||||||
VOID StopMonitor();
|
VOID StopMonitor();
|
||||||
|
|
@ -83,6 +109,8 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual ~FILE_WATCHER_ENTRY();
|
||||||
|
|
||||||
DWORD _dwSignature;
|
DWORD _dwSignature;
|
||||||
BUFFER _buffDirectoryChanges;
|
BUFFER _buffDirectoryChanges;
|
||||||
HANDLE _hImpersonationToken;
|
HANDLE _hImpersonationToken;
|
||||||
|
|
@ -92,5 +120,7 @@ private:
|
||||||
STRU _strFileName;
|
STRU _strFileName;
|
||||||
STRU _strDirectoryName;
|
STRU _strDirectoryName;
|
||||||
LONG _lStopMonitorCalled;
|
LONG _lStopMonitorCalled;
|
||||||
|
mutable LONG _cRefs;
|
||||||
|
BOOL _fIsValid;
|
||||||
SRWLOCK _srwLock;
|
SRWLOCK _srwLock;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@
|
||||||
#define IDS_SERVER_ERROR 1001
|
#define IDS_SERVER_ERROR 1001
|
||||||
|
|
||||||
#define ASPNETCORE_EVENT_MSG_BUFFER_SIZE 256
|
#define ASPNETCORE_EVENT_MSG_BUFFER_SIZE 256
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG L"Process '%d' started successfully and is listening on port '%d'."
|
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG L"Application '%s' started process '%d' successfully and 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_RAPID_FAIL_COUNT_EXCEEDED_MSG L"Maximum rapid fail count per minute of '%d' exceeded."
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG L"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"Process was created 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"Failed to start process with commandline '%s', 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_WRONGPORT_ERROR_MSG L"Process was created with commandline '%s' but did not 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"Process was created with commandline '%s' but either crashed or did not reponse within given time 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."
|
||||||
#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'."
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,11 @@ APPLICATION::~APPLICATION()
|
||||||
{
|
{
|
||||||
if (m_pFileWatcherEntry != NULL)
|
if (m_pFileWatcherEntry != NULL)
|
||||||
{
|
{
|
||||||
|
// Mark the entry as invalid,
|
||||||
|
// StopMonitor will close the file handle and trigger a FCN
|
||||||
|
// the entry will delete itself when processing this FCN
|
||||||
|
m_pFileWatcherEntry->MarkEntryInValid();
|
||||||
m_pFileWatcherEntry->StopMonitor();
|
m_pFileWatcherEntry->StopMonitor();
|
||||||
delete m_pFileWatcherEntry;
|
|
||||||
m_pFileWatcherEntry = NULL;
|
m_pFileWatcherEntry = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +79,7 @@ Finished:
|
||||||
{
|
{
|
||||||
if (m_pFileWatcherEntry != NULL)
|
if (m_pFileWatcherEntry != NULL)
|
||||||
{
|
{
|
||||||
delete m_pFileWatcherEntry;
|
m_pFileWatcherEntry->DereferenceFileWatcherEntry();
|
||||||
m_pFileWatcherEntry = NULL;
|
m_pFileWatcherEntry = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ APPLICATION_MANAGER* APPLICATION_MANAGER::sm_pApplicationManager = NULL;
|
||||||
HRESULT
|
HRESULT
|
||||||
APPLICATION_MANAGER::GetApplication(
|
APPLICATION_MANAGER::GetApplication(
|
||||||
_In_ IHttpContext* pContext,
|
_In_ IHttpContext* pContext,
|
||||||
_In_ LPCWSTR pszApplication,
|
|
||||||
_Out_ APPLICATION ** ppApplication
|
_Out_ APPLICATION ** ppApplication
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
@ -16,11 +15,15 @@ APPLICATION_MANAGER::GetApplication(
|
||||||
APPLICATION *pApplication = NULL;
|
APPLICATION *pApplication = NULL;
|
||||||
APPLICATION_KEY key;
|
APPLICATION_KEY key;
|
||||||
BOOL fExclusiveLock = FALSE;
|
BOOL fExclusiveLock = FALSE;
|
||||||
|
PCWSTR pszApplicationId = NULL;
|
||||||
|
|
||||||
*ppApplication = NULL;
|
*ppApplication = NULL;
|
||||||
|
|
||||||
hr = key.Initialize(pszApplication);
|
DBG_ASSERT(pContext != NULL);
|
||||||
|
DBG_ASSERT(pContext->GetApplication() != NULL);
|
||||||
|
pszApplicationId = pContext->GetApplication()->GetApplicationId();
|
||||||
|
|
||||||
|
hr = key.Initialize(pszApplicationId);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto Finished;
|
goto Finished;
|
||||||
|
|
@ -50,7 +53,7 @@ APPLICATION_MANAGER::GetApplication(
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pApplication->Initialize(this, pszApplication, pContext->GetApplication()->GetApplicationPhysicalPath());
|
hr = pApplication->Initialize(this, pszApplicationId, pContext->GetApplication()->GetApplicationPhysicalPath());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto Finished;
|
goto Finished;
|
||||||
|
|
@ -88,14 +91,6 @@ Finished:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
APPLICATION_MANAGER::RecycleOnFileChange(
|
|
||||||
APPLICATION_MANAGER*,
|
|
||||||
APPLICATION*
|
|
||||||
)
|
|
||||||
{
|
|
||||||
g_pHttpServer->RecycleProcess(L"Asp.Net Core Module Recycle Process on File Change Notification");
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
APPLICATION_MANAGER::RecycleApplication(
|
APPLICATION_MANAGER::RecycleApplication(
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,9 @@ ASPNETCORE_CONFIG::GetConfig(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = pAspNetCoreConfig->QueryApplicationPath()->Copy(pHttpApplication->GetAppConfigPath());
|
// set appliction info here instead of inside Populate()
|
||||||
|
// as the destructor will delete the backend process
|
||||||
|
hr = pAspNetCoreConfig->QueryApplicationPath()->Copy(pHttpApplication->GetApplicationId());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto Finished;
|
goto Finished;
|
||||||
|
|
@ -382,6 +384,7 @@ ASPNETCORE_CONFIG::Populate(
|
||||||
}
|
}
|
||||||
pcszEnvName = mszEnvNames.Next(pcszEnvName);
|
pcszEnvName = mszEnvNames.Next(pcszEnvName);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// let's disable this feature for now
|
// let's disable this feature for now
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,15 @@ FILE_WATCHER::FILE_WATCHER() :
|
||||||
m_hCompletionPort(NULL),
|
m_hCompletionPort(NULL),
|
||||||
m_hChangeNotificationThread(NULL)
|
m_hChangeNotificationThread(NULL)
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&this->m_csSyncRoot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_WATCHER::~FILE_WATCHER()
|
FILE_WATCHER::~FILE_WATCHER()
|
||||||
{
|
{
|
||||||
DeleteCriticalSection(&this->m_csSyncRoot);
|
if (m_hChangeNotificationThread != NULL)
|
||||||
|
{
|
||||||
|
CloseHandle(m_hChangeNotificationThread);
|
||||||
|
m_hChangeNotificationThread = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
@ -76,29 +79,34 @@ Win32 error
|
||||||
--*/
|
--*/
|
||||||
{
|
{
|
||||||
FILE_WATCHER * pFileMonitor;
|
FILE_WATCHER * pFileMonitor;
|
||||||
BOOL fRet = FALSE;
|
BOOL fSuccess = FALSE;
|
||||||
DWORD cbCompletion = 0;
|
DWORD cbCompletion = 0;
|
||||||
OVERLAPPED * pOverlapped = NULL;
|
OVERLAPPED * pOverlapped = NULL;
|
||||||
DWORD dwErrorStatus;
|
DWORD dwErrorStatus;
|
||||||
ULONG_PTR completionKey;
|
ULONG_PTR completionKey;
|
||||||
|
|
||||||
pFileMonitor = (FILE_WATCHER*)pvArg;
|
pFileMonitor = (FILE_WATCHER*)pvArg;
|
||||||
|
DBG_ASSERT(pFileMonitor != NULL);
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
fRet = GetQueuedCompletionStatus(
|
fSuccess = GetQueuedCompletionStatus(
|
||||||
pFileMonitor->m_hCompletionPort,
|
pFileMonitor->m_hCompletionPort,
|
||||||
&cbCompletion,
|
&cbCompletion,
|
||||||
&completionKey,
|
&completionKey,
|
||||||
&pOverlapped,
|
&pOverlapped,
|
||||||
INFINITE);
|
INFINITE);
|
||||||
|
|
||||||
dwErrorStatus = fRet ? ERROR_SUCCESS : GetLastError();
|
DBG_ASSERT(fSuccess);
|
||||||
|
DebugPrint(1, "FILE_WATCHER::ChangeNotificationThread");
|
||||||
|
dwErrorStatus = fSuccess ? ERROR_SUCCESS : GetLastError();
|
||||||
|
|
||||||
if (completionKey == FILE_WATCHER_SHUTDOWN_KEY)
|
if (completionKey == FILE_WATCHER_SHUTDOWN_KEY)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBG_ASSERT(pOverlapped != NULL);
|
||||||
if (pOverlapped != NULL)
|
if (pOverlapped != NULL)
|
||||||
{
|
{
|
||||||
FileWatcherCompletionRoutine(
|
FileWatcherCompletionRoutine(
|
||||||
|
|
@ -138,10 +146,26 @@ None
|
||||||
{
|
{
|
||||||
FILE_WATCHER_ENTRY * pMonitorEntry;
|
FILE_WATCHER_ENTRY * pMonitorEntry;
|
||||||
pMonitorEntry = CONTAINING_RECORD(pOverlapped, FILE_WATCHER_ENTRY, _overlapped);
|
pMonitorEntry = CONTAINING_RECORD(pOverlapped, FILE_WATCHER_ENTRY, _overlapped);
|
||||||
|
pMonitorEntry->DereferenceFileWatcherEntry();
|
||||||
DBG_ASSERT(pMonitorEntry != NULL);
|
DBG_ASSERT(pMonitorEntry != NULL);
|
||||||
pMonitorEntry->HandleChangeCompletion(dwCompletionStatus,
|
|
||||||
cbCompletion);
|
pMonitorEntry->HandleChangeCompletion(dwCompletionStatus, cbCompletion);
|
||||||
|
|
||||||
|
if (pMonitorEntry->QueryIsValid())
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Continue monitoring
|
||||||
|
//
|
||||||
|
pMonitorEntry->Monitor();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Marked by application distructor
|
||||||
|
// Deference the entry to delete it
|
||||||
|
//
|
||||||
|
pMonitorEntry->DereferenceFileWatcherEntry();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -150,7 +174,9 @@ FILE_WATCHER_ENTRY::FILE_WATCHER_ENTRY(FILE_WATCHER * pFileMonitor) :
|
||||||
_hDirectory(INVALID_HANDLE_VALUE),
|
_hDirectory(INVALID_HANDLE_VALUE),
|
||||||
_hImpersonationToken(NULL),
|
_hImpersonationToken(NULL),
|
||||||
_pApplication(NULL),
|
_pApplication(NULL),
|
||||||
_lStopMonitorCalled(0)
|
_lStopMonitorCalled(0),
|
||||||
|
_cRefs(1),
|
||||||
|
_fIsValid(TRUE)
|
||||||
{
|
{
|
||||||
_dwSignature = FILE_WATCHER_ENTRY_SIGNATURE;
|
_dwSignature = FILE_WATCHER_ENTRY_SIGNATURE;
|
||||||
InitializeSRWLock(&_srwLock);
|
InitializeSRWLock(&_srwLock);
|
||||||
|
|
@ -201,6 +227,12 @@ HRESULT
|
||||||
FILE_NOTIFY_INFORMATION * pNotificationInfo;
|
FILE_NOTIFY_INFORMATION * pNotificationInfo;
|
||||||
BOOL fFileChanged = FALSE;
|
BOOL fFileChanged = FALSE;
|
||||||
|
|
||||||
|
AcquireSRWLockExclusive(&_srwLock);
|
||||||
|
if (!_fIsValid)
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
// When directory handle is closed then HandleChangeCompletion
|
// When directory handle is closed then HandleChangeCompletion
|
||||||
// happens with cbCompletion = 0 and dwCompletionStatus = 0
|
// happens with cbCompletion = 0 and dwCompletionStatus = 0
|
||||||
// From documentation it is not clear if that combination
|
// From documentation it is not clear if that combination
|
||||||
|
|
@ -211,32 +243,31 @@ HRESULT
|
||||||
//
|
//
|
||||||
if (_lStopMonitorCalled)
|
if (_lStopMonitorCalled)
|
||||||
{
|
{
|
||||||
hr = S_OK;
|
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// There could be a FCN overflow
|
||||||
|
// Let assume the file got changed instead of checking files
|
||||||
|
// Othersie we have to cache the file info
|
||||||
|
//
|
||||||
if (cbCompletion == 0)
|
if (cbCompletion == 0)
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// There could be a FCN overflow
|
|
||||||
// Let assume the file got changed instead of checking files
|
|
||||||
// Othersie we have to cache the file info
|
|
||||||
//
|
|
||||||
|
|
||||||
fFileChanged = TRUE;
|
fFileChanged = TRUE;
|
||||||
hr = HRESULT_FROM_WIN32(dwCompletionStatus);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pNotificationInfo = (FILE_NOTIFY_INFORMATION*)_buffDirectoryChanges.QueryPtr();
|
pNotificationInfo = (FILE_NOTIFY_INFORMATION*)_buffDirectoryChanges.QueryPtr();
|
||||||
_ASSERT(pNotificationInfo != NULL);
|
DBG_ASSERT(pNotificationInfo != NULL);
|
||||||
|
|
||||||
while (pNotificationInfo != NULL)
|
while (pNotificationInfo != NULL)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// check whether the monitored file got changed
|
// check whether the monitored file got changed
|
||||||
//
|
//
|
||||||
if (wcscmp(pNotificationInfo->FileName, _strFileName.QueryStr()) == 0)
|
if (wcsncmp(pNotificationInfo->FileName,
|
||||||
|
_strFileName.QueryStr(),
|
||||||
|
pNotificationInfo->FileNameLength/sizeof(WCHAR)) == 0)
|
||||||
{
|
{
|
||||||
fFileChanged = TRUE;
|
fFileChanged = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
@ -255,13 +286,7 @@ HRESULT
|
||||||
pNotificationInfo->NextEntryOffset);
|
pNotificationInfo->NextEntryOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlZeroMemory(_buffDirectoryChanges.QueryPtr(), _buffDirectoryChanges.QuerySize());
|
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//continue monitoring
|
|
||||||
//
|
|
||||||
StopMonitor();
|
|
||||||
|
|
||||||
if (fFileChanged)
|
if (fFileChanged)
|
||||||
{
|
{
|
||||||
|
|
@ -271,9 +296,8 @@ HRESULT
|
||||||
_pApplication->UpdateAppOfflineFileHandle();
|
_pApplication->UpdateAppOfflineFileHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = Monitor();
|
|
||||||
|
|
||||||
Finished:
|
Finished:
|
||||||
|
ReleaseSRWLockExclusive(&_srwLock);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,69 +309,23 @@ FILE_WATCHER_ENTRY::Monitor(VOID)
|
||||||
DWORD cbRead;
|
DWORD cbRead;
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&_srwLock);
|
AcquireSRWLockExclusive(&_srwLock);
|
||||||
|
ReferenceFileWatcherEntry();
|
||||||
ZeroMemory(&_overlapped, sizeof(_overlapped));
|
ZeroMemory(&_overlapped, sizeof(_overlapped));
|
||||||
if (_hDirectory != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(_hDirectory);
|
|
||||||
_hDirectory = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_hDirectory = CreateFileW(_strDirectoryName.QueryStr(),
|
if(!ReadDirectoryChangesW(_hDirectory,
|
||||||
FILE_LIST_DIRECTORY,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
NULL,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (_hDirectory == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CreateIoCompletionPort(
|
|
||||||
_hDirectory,
|
|
||||||
_pFileMonitor->QueryCompletionPort(),
|
|
||||||
NULL,
|
|
||||||
0) == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Resize change buffer to something "reasonable"
|
|
||||||
//
|
|
||||||
fRet = _buffDirectoryChanges.Resize(4096);
|
|
||||||
if (!fRet)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
fRet = ReadDirectoryChangesW(_hDirectory,
|
|
||||||
_buffDirectoryChanges.QueryPtr(),
|
_buffDirectoryChanges.QueryPtr(),
|
||||||
_buffDirectoryChanges.QuerySize(),
|
_buffDirectoryChanges.QuerySize(),
|
||||||
FALSE, // watch sub dirs. set to False now as only monitoring app_offline
|
FALSE, // Watching sub dirs. Set to False now as only monitoring app_offline
|
||||||
FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS & ~FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS & ~FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
||||||
&cbRead,
|
&cbRead,
|
||||||
&_overlapped,
|
&_overlapped,
|
||||||
NULL);
|
NULL))
|
||||||
|
|
||||||
if (!fRet)
|
|
||||||
{
|
{
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
InterlockedExchange(&_lStopMonitorCalled, 0);
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
ReleaseSRWLockExclusive(&_srwLock);
|
ReleaseSRWLockExclusive(&_srwLock);
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
@ -386,7 +364,7 @@ FILE_WATCHER_ENTRY::Create(
|
||||||
pszFileNameToMonitor == NULL ||
|
pszFileNameToMonitor == NULL ||
|
||||||
pApplication == NULL)
|
pApplication == NULL)
|
||||||
{
|
{
|
||||||
_ASSERT(FALSE);
|
DBG_ASSERT(FALSE);
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
@ -406,6 +384,15 @@ FILE_WATCHER_ENTRY::Create(
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Resize change buffer to something "reasonable"
|
||||||
|
//
|
||||||
|
if (!_buffDirectoryChanges.Resize(FILE_WATCHER_ENTRY_BUFFER_SIZE))
|
||||||
|
{
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
if (hImpersonationToken != NULL)
|
if (hImpersonationToken != NULL)
|
||||||
{
|
{
|
||||||
fRet = DuplicateHandle(GetCurrentProcess(),
|
fRet = DuplicateHandle(GetCurrentProcess(),
|
||||||
|
|
@ -430,6 +417,32 @@ FILE_WATCHER_ENTRY::Create(
|
||||||
_hImpersonationToken = NULL;
|
_hImpersonationToken = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_hDirectory = CreateFileW(
|
||||||
|
_strDirectoryName.QueryStr(),
|
||||||
|
FILE_LIST_DIRECTORY,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (_hDirectory == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CreateIoCompletionPort(
|
||||||
|
_hDirectory,
|
||||||
|
_pFileMonitor->QueryCompletionPort(),
|
||||||
|
NULL,
|
||||||
|
0) == NULL)
|
||||||
|
{
|
||||||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Start monitoring
|
// Start monitoring
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -359,18 +359,10 @@ FORWARDING_HANDLER::SetStatusAndHeaders(
|
||||||
DWORD headerIndex = g_pResponseHeaderHash->GetIndex(strHeaderName.QueryStr());
|
DWORD headerIndex = g_pResponseHeaderHash->GetIndex(strHeaderName.QueryStr());
|
||||||
if (headerIndex == UNKNOWN_INDEX)
|
if (headerIndex == UNKNOWN_INDEX)
|
||||||
{
|
{
|
||||||
if (_strnicmp(strHeaderName.QueryStr(), "Sec-WebSocket", 13) != 0 )
|
hr = pResponse->SetHeader(strHeaderName.QueryStr(),
|
||||||
{
|
strHeaderValue.QueryStr(),
|
||||||
//
|
static_cast<USHORT>(strHeaderValue.QueryCCH()),
|
||||||
// Perf Opt: Avoid setting websocket headers, since IIS websocket module
|
FALSE); // fReplace
|
||||||
// will anyways set these later in the pipeline.
|
|
||||||
//
|
|
||||||
|
|
||||||
hr = pResponse->SetHeader(strHeaderName.QueryStr(),
|
|
||||||
strHeaderValue.QueryStr(),
|
|
||||||
static_cast<USHORT>(strHeaderValue.QueryCCH()),
|
|
||||||
FALSE); // fReplace
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1074,7 +1066,6 @@ VOID
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pApplicationManager->GetApplication( m_pW3Context,
|
hr = pApplicationManager->GetApplication( m_pW3Context,
|
||||||
m_pW3Context->GetApplication()->GetAppConfigPath(),
|
|
||||||
&m_pApplication );
|
&m_pApplication );
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ SERVER_PROCESS::StartProcess(
|
||||||
WCHAR* pszPath = NULL;
|
WCHAR* pszPath = NULL;
|
||||||
WCHAR pszFullPath[_MAX_PATH];
|
WCHAR pszFullPath[_MAX_PATH];
|
||||||
LPCWSTR apsz[1];
|
LPCWSTR apsz[1];
|
||||||
|
PCWSTR pszAppPath = NULL;
|
||||||
|
|
||||||
GetStartupInfoW(&startupInfo);
|
GetStartupInfoW(&startupInfo);
|
||||||
|
|
||||||
|
|
@ -243,8 +244,6 @@ SERVER_PROCESS::StartProcess(
|
||||||
|
|
||||||
struApplicationId.Copy( L"ASPNETCORE_APPL_PATH=" );
|
struApplicationId.Copy( L"ASPNETCORE_APPL_PATH=" );
|
||||||
|
|
||||||
PCWSTR pszAppPath = NULL;
|
|
||||||
|
|
||||||
// let's find the app path. IIS does not support nested sites
|
// let's find the app path. IIS does not support nested sites
|
||||||
// we can seek for the fourth '/' if it exits
|
// we can seek for the fourth '/' if it exits
|
||||||
// MACHINE/WEBROOT/APPHOST/<site>/<app>.
|
// MACHINE/WEBROOT/APPHOST/<site>/<app>.
|
||||||
|
|
@ -277,7 +276,7 @@ SERVER_PROCESS::StartProcess(
|
||||||
|
|
||||||
mszNewEnvironment.Append( struGuidEnv );
|
mszNewEnvironment.Append( struGuidEnv );
|
||||||
|
|
||||||
pszRootApplicationPath = context->GetRootContext()->GetApplication()->GetApplicationPhysicalPath();
|
pszRootApplicationPath = context->GetApplication()->GetApplicationPhysicalPath();
|
||||||
|
|
||||||
//
|
//
|
||||||
// generate process command line.
|
// generate process command line.
|
||||||
|
|
@ -486,8 +485,11 @@ SERVER_PROCESS::StartProcess(
|
||||||
// don't check return code as we already in error report
|
// don't check return code as we already in error report
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG,
|
||||||
|
pszAppPath,
|
||||||
|
pszRootApplicationPath,
|
||||||
finalCommandLine.QueryStr(),
|
finalCommandLine.QueryStr(),
|
||||||
hr);
|
hr,
|
||||||
|
0);
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -537,8 +539,11 @@ SERVER_PROCESS::StartProcess(
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG,
|
||||||
|
pszAppPath,
|
||||||
|
pszRootApplicationPath,
|
||||||
finalCommandLine.QueryStr(),
|
finalCommandLine.QueryStr(),
|
||||||
hr);
|
hr,
|
||||||
|
processStatus);
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -632,6 +637,8 @@ SERVER_PROCESS::StartProcess(
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
|
hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG,
|
||||||
|
pszAppPath,
|
||||||
|
pszRootApplicationPath,
|
||||||
finalCommandLine.QueryStr(),
|
finalCommandLine.QueryStr(),
|
||||||
m_dwPort,
|
m_dwPort,
|
||||||
hr);
|
hr);
|
||||||
|
|
@ -649,6 +656,8 @@ SERVER_PROCESS::StartProcess(
|
||||||
fReady = FALSE;
|
fReady = FALSE;
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_WRONGPORT_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_WRONGPORT_ERROR_MSG,
|
||||||
|
pszAppPath,
|
||||||
|
pszRootApplicationPath,
|
||||||
finalCommandLine.QueryStr(),
|
finalCommandLine.QueryStr(),
|
||||||
m_dwPort,
|
m_dwPort,
|
||||||
hr);
|
hr);
|
||||||
|
|
@ -678,6 +687,8 @@ SERVER_PROCESS::StartProcess(
|
||||||
{
|
{
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG,
|
||||||
|
pszAppPath,
|
||||||
|
pszRootApplicationPath,
|
||||||
finalCommandLine.QueryStr(),
|
finalCommandLine.QueryStr(),
|
||||||
m_dwPort,
|
m_dwPort,
|
||||||
hr);
|
hr);
|
||||||
|
|
@ -724,6 +735,7 @@ SERVER_PROCESS::StartProcess(
|
||||||
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG,
|
||||||
|
pszAppPath,
|
||||||
m_dwProcessId,
|
m_dwProcessId,
|
||||||
m_dwPort)))
|
m_dwPort)))
|
||||||
{
|
{
|
||||||
|
|
@ -754,11 +766,14 @@ Finished:
|
||||||
{
|
{
|
||||||
if (!fDonePrepareCommandLine)
|
if (!fDonePrepareCommandLine)
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
|
pszAppPath,
|
||||||
ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG,
|
||||||
hr);
|
hr);
|
||||||
else
|
else
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG,
|
||||||
|
pszAppPath,
|
||||||
|
pszRootApplicationPath,
|
||||||
finalCommandLine.QueryStr(),
|
finalCommandLine.QueryStr(),
|
||||||
hr);
|
hr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue