Skip to content

Commit a45a3dd

Browse files
committed
General functionality working, whole lot of cleanup now
1 parent 427cb26 commit a45a3dd

File tree

3 files changed

+100
-16
lines changed

3 files changed

+100
-16
lines changed

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

+84-14
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,26 @@
66
#include "debugutil.h"
77
#include "AppOfflineTrackingApplication.h"
88
#include "exceptions.h"
9+
#include <EventLog.h>
910

1011
FILE_WATCHER::FILE_WATCHER() :
1112
m_hCompletionPort(NULL),
1213
m_hChangeNotificationThread(NULL),
1314
m_fThreadExit(FALSE),
14-
_fTrackDllChanges(FALSE)
15+
_fTrackDllChanges(FALSE),
16+
m_copied(false)
1517
{
18+
m_pShutdownEvent = CreateEvent(
19+
nullptr, // default security attributes
20+
TRUE, // manual reset event
21+
FALSE, // not set
22+
nullptr); // name
1623
}
1724

1825
FILE_WATCHER::~FILE_WATCHER()
1926
{
2027
StopMonitor();
21-
WaitForMonitor(20);
28+
WaitForMonitor(20000);
2229
}
2330

2431
void FILE_WATCHER::WaitForMonitor(DWORD dwRetryCounter)
@@ -60,7 +67,7 @@ FILE_WATCHER::Create(
6067
_In_ PCWSTR pszFileNameToMonitor,
6168
_In_ bool fTrackDllChanges,
6269
_In_ std::wstring shadowCopyPath,
63-
_In_ AppOfflineTrackingApplication *pApplication
70+
_In_ AppOfflineTrackingApplication* pApplication
6471
)
6572
{
6673
_shadowCopyPath = shadowCopyPath;
@@ -138,10 +145,10 @@ Win32 error
138145
139146
--*/
140147
{
141-
FILE_WATCHER * pFileMonitor;
148+
FILE_WATCHER* pFileMonitor;
142149
BOOL fSuccess = FALSE;
143150
DWORD cbCompletion = 0;
144-
OVERLAPPED * pOverlapped = NULL;
151+
OVERLAPPED* pOverlapped = NULL;
145152
DWORD dwErrorStatus;
146153
ULONG_PTR completionKey;
147154

@@ -185,7 +192,15 @@ Win32 error
185192

186193
pFileMonitor->m_fThreadExit = TRUE;
187194

195+
// TODO check instead for if a dll was changed here
196+
if (pFileMonitor->_fTrackDllChanges)
197+
{
198+
pFileMonitor->m_Timer.CancelTimer();
199+
FILE_WATCHER::CopyAndShutdown(pFileMonitor);
200+
}
201+
188202
LOG_INFO(L"Stopping file watcher thread");
203+
189204
ExitThread(0);
190205
}
191206

@@ -265,6 +280,7 @@ HRESULT
265280
if (_fTrackDllChanges && notificationPath.extension().compare(L".dll") == 0)
266281
{
267282
fFileChanged = TRUE;
283+
_fDllHadChanged = true;
268284
fDllChanged = TRUE;
269285
}
270286

@@ -288,21 +304,72 @@ HRESULT
288304
{
289305
// Reference application before
290306
_pApplication->ReferenceApplication();
291-
if (fDllChanged)
307+
if (fDllChanged || _fTrackDllChanges)
292308
{
293-
// wait for all file changes to complete
294-
PostQueuedCompletionStatus(m_hCompletionPort, 0, FILE_WATCHER_SHUTDOWN_KEY, NULL);
295-
WaitForMonitor(100); // 5 seconds here.
296-
297-
// Copy contents before shutdown
298-
RETURN_IF_FAILED(Environment::CopyToDirectory(_shadowCopyPath, _strDirectoryName.QueryStr(), false));
309+
// Call shutdown later.
310+
m_Timer.CancelTimer();
311+
m_Timer.InitializeTimer(FILE_WATCHER::TimerCallback, this, 5000, 3000);
312+
}
313+
else
314+
{
315+
RETURN_LAST_ERROR_IF(!QueueUserWorkItem(RunNotificationCallback, _pApplication.get(), WT_EXECUTEDEFAULT));
299316
}
300-
RETURN_LAST_ERROR_IF(!QueueUserWorkItem(RunNotificationCallback, _pApplication.get(), WT_EXECUTEDEFAULT));
301317
}
302318

303319
return S_OK;
304320
}
305321

322+
323+
VOID
324+
CALLBACK
325+
FILE_WATCHER::TimerCallback(
326+
_In_ PTP_CALLBACK_INSTANCE Instance,
327+
_In_ PVOID Context,
328+
_In_ PTP_TIMER Timer
329+
)
330+
{
331+
// Need to lock here.
332+
Instance;
333+
Timer;
334+
CopyAndShutdown((FILE_WATCHER*)Context);
335+
}
336+
337+
DWORD WINAPI FILE_WATCHER::CopyAndShutdown(LPVOID arg)
338+
{
339+
EventLog::Error(
340+
1,
341+
L"Callback");
342+
auto directoryName = 0;
343+
// wrong path.
344+
auto watcher = (FILE_WATCHER*)arg;
345+
SRWExclusiveLock lock(watcher->m_copyLock);
346+
347+
if (watcher->m_copied)
348+
{
349+
return 0;
350+
}
351+
352+
watcher->m_copied = true;
353+
354+
auto dir = std::filesystem::path(watcher->_shadowCopyPath);
355+
auto parent = dir.parent_path();
356+
directoryName = std::stoi(dir.filename().string());
357+
358+
directoryName++;
359+
auto dirNameStr = std::to_wstring(directoryName);
360+
auto destination = parent / dirNameStr.c_str();
361+
362+
// Copy contents before shutdown
363+
Environment::CopyToDirectory(destination, watcher->_strDirectoryName.QueryStr(), false);
364+
365+
watcher->_pApplication->ReferenceApplication();
366+
SetEvent(watcher->m_pShutdownEvent);
367+
368+
QueueUserWorkItem(RunNotificationCallback, watcher->_pApplication.get(), WT_EXECUTEDEFAULT);
369+
return 0;
370+
}
371+
372+
306373
DWORD
307374
WINAPI
308375
FILE_WATCHER::RunNotificationCallback(
@@ -311,7 +378,6 @@ FILE_WATCHER::RunNotificationCallback(
311378
{
312379
// Recapture application instance into unique_ptr
313380
auto pApplication = std::unique_ptr<AppOfflineTrackingApplication, IAPPLICATION_DELETER>(static_cast<AppOfflineTrackingApplication*>(pvArg));
314-
DBG_ASSERT(pFileMonitor != NULL);
315381
pApplication->OnAppOffline();
316382

317383
return 0;
@@ -359,6 +425,10 @@ FILE_WATCHER::StopMonitor()
359425
InterlockedExchange(&_lStopMonitorCalled, 1);
360426
// signal the file watch thread to exit
361427
PostQueuedCompletionStatus(m_hCompletionPort, 0, FILE_WATCHER_SHUTDOWN_KEY, NULL);
428+
WaitForMonitor(20000);
429+
// See if this waits.
430+
WaitForSingleObject(m_pShutdownEvent, 120000);
431+
362432
// Release application reference
363433
_pApplication.reset(nullptr);
364434
}

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

+14
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "iapplication.h"
1010
#include "HandleWrapper.h"
1111
#include "Environment.h"
12+
#include <sttimer.h>
1213

1314
#define FILE_WATCHER_SHUTDOWN_KEY (ULONG_PTR)(-1)
1415
#define FILE_WATCHER_ENTRY_BUFFER_SIZE 4096
@@ -41,6 +42,14 @@ class FILE_WATCHER{
4142
DWORD
4243
WINAPI RunNotificationCallback(LPVOID);
4344

45+
static
46+
VOID
47+
WINAPI TimerCallback(_In_ PTP_CALLBACK_INSTANCE Instance,
48+
_In_ PVOID Context,
49+
_In_ PTP_TIMER Timer);
50+
51+
static DWORD WINAPI CopyAndShutdown(LPVOID);
52+
4453
HRESULT HandleChangeCompletion(DWORD cbCompletion);
4554

4655
HRESULT Monitor();
@@ -50,14 +59,19 @@ class FILE_WATCHER{
5059
HandleWrapper<NullHandleTraits> m_hCompletionPort;
5160
HandleWrapper<NullHandleTraits> m_hChangeNotificationThread;
5261
HandleWrapper<NullHandleTraits> _hDirectory;
62+
HandleWrapper<NullHandleTraits> m_pShutdownEvent;
5363
volatile BOOL m_fThreadExit;
64+
STTIMER m_Timer;
65+
SRWLOCK m_copyLock{};
66+
BOOL m_copied;
5467

5568
BUFFER _buffDirectoryChanges;
5669
STRU _strFileName;
5770
STRU _strDirectoryName;
5871
STRU _strFullName;
5972
LONG _lStopMonitorCalled {};
6073
bool _fTrackDllChanges;
74+
bool _fDllHadChanged;
6175
std::wstring _shadowCopyPath;
6276
OVERLAPPED _overlapped;
6377
std::unique_ptr<AppOfflineTrackingApplication, IAPPLICATION_DELETER> _pApplication;

src/Servers/IIS/IIS/test/Common.FunctionalTests/ShadowCopyTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public async Task ShadowCopyE2EWorks()
152152
deploymentParameters.HandlerSettings["shadowCopyDirectory"] = directory.FullName;
153153
var deploymentResult = await DeployAsync(deploymentParameters);
154154

155-
DirectoryCopy(deploymentResult.ContentRoot, directory.FullName, copySubDirs: true);
155+
//DirectoryCopy(deploymentResult.ContentRoot, Path.Combine(directory.FullName, "0"), copySubDirs: true);
156156

157157
await deploymentResult.HttpClient.GetStringAsync("Wow!");
158158

@@ -164,7 +164,7 @@ public async Task ShadowCopyE2EWorks()
164164

165165
deploymentResult.AssertWorkerProcessStop();
166166

167-
EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.ShutdownFileChange(deploymentResult), Logger);
167+
//EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.ShutdownFileChange(deploymentResult), Logger);
168168
}
169169

170170
protected static DirectoryInfo CreateTempDirectory()

0 commit comments

Comments
 (0)