Skip to content

Commit c1d8525

Browse files
Update ANCM file monitoring to hopefully avoid unneeded shutdowns (#57735)
1 parent e82706a commit c1d8525

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/AppOfflineTrackingApplication.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class AppOfflineTrackingApplication: public APPLICATION
1616
m_applicationPath(application.GetApplicationPhysicalPath()),
1717
m_fileWatcher(nullptr),
1818
m_fAppOfflineProcessed(false),
19-
m_shutdownTimeout(120000) // default to 2 minutes
19+
m_shutdownTimeout(120000), // default to 2 minutes
20+
m_detectedAppOffline(false)
2021
{
2122
}
2223

src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/filewatcher.cpp

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,21 @@ Win32 error
172172
while (true)
173173
{
174174

175-
DWORD cbCompletion = 0;
175+
DWORD bytesTransferred = 0;
176176
OVERLAPPED* pOverlapped = nullptr;
177177
ULONG_PTR completionKey;
178178

179179
BOOL success = GetQueuedCompletionStatus(
180180
pFileMonitor->m_hCompletionPort,
181-
&cbCompletion,
181+
&bytesTransferred,
182182
&completionKey,
183183
&pOverlapped,
184184
INFINITE);
185185

186-
DBG_ASSERT(success);
187-
(void)success;
186+
if (!success)
187+
{
188+
LOG_INFOF(L"Failure when watching app directory. HR: 0x%x", HRESULT_FROM_WIN32(GetLastError()));
189+
}
188190

189191
if (completionKey == FILE_WATCHER_SHUTDOWN_KEY)
190192
{
@@ -194,7 +196,7 @@ Win32 error
194196
DBG_ASSERT(pOverlapped != nullptr);
195197
if (pOverlapped != nullptr)
196198
{
197-
pFileMonitor->HandleChangeCompletion(cbCompletion);
199+
pFileMonitor->HandleChangeCompletion(bytesTransferred);
198200

199201
if (!pFileMonitor->_lStopMonitorCalled)
200202
{
@@ -222,7 +224,7 @@ Win32 error
222224

223225
HRESULT
224226
FILE_WATCHER::HandleChangeCompletion(
225-
_In_ DWORD cbCompletion
227+
_In_ DWORD bytesTransferred
226228
)
227229
/*++
228230
@@ -234,7 +236,7 @@ need to be flushed)
234236
Arguments:
235237
236238
dwCompletionStatus - Completion status
237-
cbCompletion - Bytes of completion
239+
bytesTransferred - Bytes of completion
238240
239241
Return Value:
240242
@@ -259,13 +261,28 @@ HRESULT
259261
}
260262

261263
//
262-
// There could be a FCN overflow
263-
// Let assume the file got changed instead of checking files
264-
// Otherwise we have to cache the file info
264+
// There could be a FCN overflow, see https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-readdirectorychangesw#remarks
265+
// specifically about lpBytesReturned being zero on a successful call
265266
//
266-
if (cbCompletion == 0)
267+
// We'll do a manual check for the existence of app_offline.htm since it's possible the file was added
268+
// When ShadowCopy is enabled we also look for .dll changes, in order to detect a dll change in this edge case we'd need to cache all dll information
269+
// and manually iterate over the directory and compare the file attributes. For now we'll assume that if dlls are changing we'll get another
270+
// file change notification in that case
271+
//
272+
if (bytesTransferred == 0)
267273
{
268-
fAppOfflineChanged = TRUE;
274+
LOG_INFO(L"0 bytes transferred for file notifications. Falling back to manually looking for app_offline.");
275+
DWORD fileAttr = GetFileAttributesW(_strFullName.QueryStr());
276+
if (fileAttr != INVALID_FILE_ATTRIBUTES && !(fileAttr & FILE_ATTRIBUTE_DIRECTORY))
277+
{
278+
fAppOfflineChanged = TRUE;
279+
auto app = _pApplication.get();
280+
app->m_detectedAppOffline = true;
281+
}
282+
else
283+
{
284+
return S_OK;
285+
}
269286
}
270287
else
271288
{
@@ -277,7 +294,8 @@ HRESULT
277294
//
278295
// check whether the monitored file got changed
279296
//
280-
if (_wcsnicmp(pNotificationInfo->FileName,
297+
if (_strFileName.QuerySizeCCH() == (pNotificationInfo->FileNameLength / sizeof(WCHAR))
298+
&& _wcsnicmp(pNotificationInfo->FileName,
281299
_strFileName.QueryStr(),
282300
pNotificationInfo->FileNameLength / sizeof(WCHAR)) == 0)
283301
{
@@ -427,7 +445,7 @@ FILE_WATCHER::Monitor(VOID)
427445
_buffDirectoryChanges.QueryPtr(),
428446
_buffDirectoryChanges.QuerySize(),
429447
FALSE, // Watching sub dirs. Set to False now as only monitoring app_offline
430-
FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS,
448+
FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS & ~FILE_NOTIFY_CHANGE_SECURITY & ~FILE_NOTIFY_CHANGE_ATTRIBUTES,
431449
&cbRead,
432450
&_overlapped,
433451
nullptr));

0 commit comments

Comments
 (0)