Skip to content

Commit 2326930

Browse files
committed
Avoid race condition
1 parent 90b072a commit 2326930

File tree

3 files changed

+86
-10
lines changed

3 files changed

+86
-10
lines changed

src/Files.App.Storage/Windows/Managers/JumpListManager.cs

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public unsafe class JumpListManager : IDisposable
3131
private FileSystemWatcher? _filesADLStoreFileWatcher;
3232
private FileSystemWatcher? _filesCDLStoreFileWatcher;
3333

34+
private readonly Lock _updateJumpListLock = new();
35+
3436
public static event EventHandler? ExplorerJumpListChanged;
3537
public static event EventHandler? FilesJumpListChanged;
3638

@@ -53,7 +55,9 @@ public HRESULT PullJumpListFromExplorer(int maxCount = 200)
5355
{
5456
try
5557
{
56-
// This method changes the jump list of Files, so we disable the watcher temporarily
58+
// Disable all watchers that could be triggered by this operation
59+
if (_explorerADLStoreFileWatcher is not null && _explorerADLStoreFileWatcher.EnableRaisingEvents)
60+
_explorerADLStoreFileWatcher.EnableRaisingEvents = false;
5761
if (_filesADLStoreFileWatcher is not null && _filesADLStoreFileWatcher.EnableRaisingEvents)
5862
_filesADLStoreFileWatcher.EnableRaisingEvents = false;
5963
if (_filesCDLStoreFileWatcher is not null && _filesCDLStoreFileWatcher.EnableRaisingEvents)
@@ -178,6 +182,9 @@ public HRESULT PullJumpListFromExplorer(int maxCount = 200)
178182
}
179183
finally
180184
{
185+
// Re-enable all watchers
186+
if (_explorerADLStoreFileWatcher is not null && !_explorerADLStoreFileWatcher.EnableRaisingEvents)
187+
_explorerADLStoreFileWatcher.EnableRaisingEvents = true;
181188
if (_filesADLStoreFileWatcher is not null && !_filesADLStoreFileWatcher.EnableRaisingEvents)
182189
_filesADLStoreFileWatcher.EnableRaisingEvents = true;
183190
if (_filesCDLStoreFileWatcher is not null && !_filesCDLStoreFileWatcher.EnableRaisingEvents)
@@ -189,8 +196,13 @@ public HRESULT PushJumpListToExplorer(int maxCount = 200)
189196
{
190197
try
191198
{
199+
// Disable all watchers that could be triggered by this operation
192200
if (_explorerADLStoreFileWatcher is not null && _explorerADLStoreFileWatcher.EnableRaisingEvents)
193201
_explorerADLStoreFileWatcher.EnableRaisingEvents = false;
202+
if (_filesADLStoreFileWatcher is not null && _filesADLStoreFileWatcher.EnableRaisingEvents)
203+
_filesADLStoreFileWatcher.EnableRaisingEvents = false;
204+
if (_filesCDLStoreFileWatcher is not null && _filesCDLStoreFileWatcher.EnableRaisingEvents)
205+
_filesCDLStoreFileWatcher.EnableRaisingEvents = false;
194206

195207
HRESULT hr;
196208

@@ -253,7 +265,7 @@ category.Type is not APPDESTCATEGORYTYPE.CUSTOM ||
253265
if (FAILED(hr)) return hr;
254266

255267
// Get the count of items in the "Recent" category
256-
uint countOfItems = 0U;
268+
uint countOfItems = 0U;
257269
hr = poc.Get()->GetCount(&countOfItems);
258270
if (FAILED(hr)) return hr;
259271

@@ -333,8 +345,13 @@ category.Type is not APPDESTCATEGORYTYPE.CUSTOM ||
333345
}
334346
finally
335347
{
348+
// Re-enable all watchers
336349
if (_explorerADLStoreFileWatcher is not null && !_explorerADLStoreFileWatcher.EnableRaisingEvents)
337350
_explorerADLStoreFileWatcher.EnableRaisingEvents = true;
351+
if (_filesADLStoreFileWatcher is not null && !_filesADLStoreFileWatcher.EnableRaisingEvents)
352+
_filesADLStoreFileWatcher.EnableRaisingEvents = true;
353+
if (_filesCDLStoreFileWatcher is not null && !_filesCDLStoreFileWatcher.EnableRaisingEvents)
354+
_filesCDLStoreFileWatcher.EnableRaisingEvents = true;
338355
}
339356
}
340357

@@ -399,7 +416,27 @@ public bool WatchJumpListChanges(string aumidCrcHash)
399416
}
400417
catch
401418
{
402-
// Gracefully exit if we can't monitor the file
419+
if (_explorerADLStoreFileWatcher is not null)
420+
{
421+
_explorerADLStoreFileWatcher.EnableRaisingEvents = false;
422+
_explorerADLStoreFileWatcher.Changed -= ExplorerJumpListWatcher_Changed;
423+
_explorerADLStoreFileWatcher.Dispose();
424+
}
425+
426+
if (_filesADLStoreFileWatcher is not null)
427+
{
428+
_filesADLStoreFileWatcher.EnableRaisingEvents = false;
429+
_filesADLStoreFileWatcher.Changed -= FilesJumpListWatcher_Changed;
430+
_filesADLStoreFileWatcher.Dispose();
431+
}
432+
433+
if (_filesCDLStoreFileWatcher is not null)
434+
{
435+
_filesCDLStoreFileWatcher.EnableRaisingEvents = false;
436+
_filesCDLStoreFileWatcher.Changed -= FilesJumpListWatcher_Changed;
437+
_filesCDLStoreFileWatcher.Dispose();
438+
}
439+
403440
return false;
404441
}
405442

@@ -462,7 +499,7 @@ private HRESULT CreateLinkFromItem(IShellItem* psi, IShellLinkW** ppsl)
462499
if (FAILED(hr)) return hr;
463500

464501
hr = pps.Get()->Commit();
465-
if (FAILED(hr)) return hr;
502+
if (FAILED(hr)) return hr;
466503

467504
hr = PInvoke.PropVariantClear(&PVAR_Title);
468505
if (FAILED(hr)) return hr;
@@ -490,31 +527,66 @@ private HRESULT GetFolderIconLocation(IShellItem* psi, PWSTR* pIconFilePath, uin
490527

491528
private void ExplorerJumpListWatcher_Changed(object sender, FileSystemEventArgs e)
492529
{
493-
PullJumpListFromExplorer();
530+
_ = STATask.Run(() =>
531+
{
532+
if (_updateJumpListLock.TryEnter())
533+
{
534+
try
535+
{
536+
Debug.WriteLine("in: ExplorerJumpListWatcher_Changed");
537+
PullJumpListFromExplorer();
538+
Debug.WriteLine("out: ExplorerJumpListWatcher_Changed");
539+
}
540+
finally
541+
{
542+
_updateJumpListLock.Exit();
543+
}
544+
}
545+
},
546+
null);
494547
}
495548

496549
private void FilesJumpListWatcher_Changed(object sender, FileSystemEventArgs e)
497550
{
498-
PushJumpListToExplorer();
551+
_ = STATask.Run(() =>
552+
{
553+
if (_updateJumpListLock.TryEnter())
554+
{
555+
try
556+
{
557+
Debug.WriteLine("in: FilesJumpListWatcher_Changed");
558+
PushJumpListToExplorer();
559+
Debug.WriteLine("out: FilesJumpListWatcher_Changed");
560+
}
561+
finally
562+
{
563+
_updateJumpListLock.Exit();
564+
}
565+
}
566+
},
567+
null);
499568
}
500569

501570
public void Dispose()
502571
{
503572
if (_explorerADLStoreFileWatcher is not null)
504573
{
505574
_explorerADLStoreFileWatcher.EnableRaisingEvents = false;
575+
_explorerADLStoreFileWatcher.Changed -= ExplorerJumpListWatcher_Changed;
506576
_explorerADLStoreFileWatcher.Dispose();
507577
}
508578

509579
if (_filesADLStoreFileWatcher is not null)
510580
{
511581
_filesADLStoreFileWatcher.EnableRaisingEvents = false;
582+
_filesADLStoreFileWatcher.Changed -= FilesJumpListWatcher_Changed;
512583
_filesADLStoreFileWatcher.Dispose();
513584
}
514585

515586
if (_filesCDLStoreFileWatcher is not null)
516587
{
517588
_filesCDLStoreFileWatcher.EnableRaisingEvents = false;
589+
_filesCDLStoreFileWatcher.Changed -= FilesJumpListWatcher_Changed;
518590
_filesCDLStoreFileWatcher.Dispose();
519591
}
520592
}

src/Files.App/Helpers/Application/AppLifecycleHelper.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@
1212
using Sentry;
1313
using Sentry.Protocol;
1414
using System.IO;
15-
using System.Runtime.InteropServices;
1615
using System.Text;
1716
using Windows.ApplicationModel;
18-
using Windows.Media.Playback;
1917
using Windows.Storage;
2018
using Windows.System;
2119
using Windows.Win32.Foundation;
@@ -169,7 +167,7 @@ await Task.WhenAll(
169167
if (JumpListManager is not null)
170168
{
171169
HRESULT hr = JumpListManager.PullJumpListFromExplorer();
172-
if (hr.Failed) App.Logger.LogWarning("Failed to synchronizing jump list unexpectedly.");
170+
if (hr.Failed) App.Logger.LogWarning("Failed to synchronize jump list unexpectedly.");
173171

174172
bool result = JumpListManager.WatchJumpListChanges(AppUserModelIdCrcHash);
175173
if (!result) App.Logger.LogWarning("Failed to watch jump list unexpectedly.");

src/Files.App/ViewModels/ShellViewModel.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,13 @@ public async Task SetWorkingDirectoryAsync(string? value)
228228
if (value == "Home" || value == "ReleaseNotes" || value == "Settings")
229229
currentStorageFolder = null;
230230
else
231-
AppLifecycleHelper.JumpListManager?.AddFolderToRecentCategory(value);
231+
{
232+
_ = STATask.Run(() =>
233+
{
234+
AppLifecycleHelper.JumpListManager?.AddFolderToRecentCategory(value);
235+
},
236+
App.Logger);
237+
}
232238

233239
WorkingDirectory = value;
234240

0 commit comments

Comments
 (0)