提交 b7330c83 编写于 作者: J Jason Malinowski

Swallow some exceptions in FileChangeTracker that are for transient issues

FileChangeTracker is subject to the evils of the file system, and
thus we swallow a few top-hitting exceptions that we shouldn't be
crashing on. For FileNotFoundException, we'll still log a non-fatal
telemetry event so we can continue to drive some fixes into the core
VS service.
上级 022a6268
......@@ -15,7 +15,7 @@ internal sealed class FileChangeTracker : IVsFileChangeEvents, IDisposable
{
private const uint FileChangeFlags = (uint)(_VSFILECHANGEFLAGS.VSFILECHG_Time | _VSFILECHANGEFLAGS.VSFILECHG_Add | _VSFILECHANGEFLAGS.VSFILECHG_Del | _VSFILECHANGEFLAGS.VSFILECHG_Size);
private static readonly Lazy<uint> s_none = new Lazy<uint>(() => /* value doesn't matter*/ 42424242, LazyThreadSafetyMode.ExecutionAndPublication);
private static readonly Lazy<uint?> s_none = new Lazy<uint?>(() => null, LazyThreadSafetyMode.ExecutionAndPublication);
private readonly IVsFileChangeEx _fileChangeService;
private readonly string _filePath;
......@@ -23,9 +23,10 @@ internal sealed class FileChangeTracker : IVsFileChangeEvents, IDisposable
/// <summary>
/// The cookie received from the IVsFileChangeEx interface that is watching for changes to
/// this file.
/// this file. This field may never be null, but might be a Lazy that has a value of null if
/// we either failed to subscribe over never have tried to subscribe.
/// </summary>
private Lazy<uint> _fileChangeCookie;
private Lazy<uint?> _fileChangeCookie;
public event EventHandler UpdatedOnDisk;
......@@ -87,11 +88,18 @@ public void StartFileChangeListeningAsync()
Contract.ThrowIfTrue(_fileChangeCookie != s_none);
_fileChangeCookie = new Lazy<uint>(() =>
_fileChangeCookie = new Lazy<uint?>(() =>
{
Marshal.ThrowExceptionForHR(
_fileChangeService.AdviseFileChange(_filePath, FileChangeFlags, this, out var newCookie));
return newCookie;
try
{
Marshal.ThrowExceptionForHR(
_fileChangeService.AdviseFileChange(_filePath, FileChangeFlags, this, out var newCookie));
return newCookie;
}
catch (Exception e) when (ShouldTrapException(e))
{
return null;
}
}, LazyThreadSafetyMode.ExecutionAndPublication);
lock (s_lastBackgroundTaskGate)
......@@ -100,6 +108,27 @@ public void StartFileChangeListeningAsync()
}
}
private static bool ShouldTrapException(Exception e)
{
if (e is FileNotFoundException)
{
// The IVsFileChange implementation shouldn't ever be throwing exceptions like this, but it's a
// transient file system issue (perhaps the file being deleted while we're changing subscriptions)
// and so there's nothing better to do. We'll still non-fatal to track the rate this is happening
return FatalError.ReportWithoutCrash(e);
}
else if (e is PathTooLongException)
{
// Nothing better we can do. We won't be able to open this file either, and thus we'll do our usual
// reporting of unopenable/missing files to the output window as usual.
return true;
}
else
{
return false;
}
}
public void StopFileChangeListening()
{
if (_disposed)
......@@ -110,18 +139,25 @@ public void StopFileChangeListening()
// there is a slight chance that we haven't subscribed to the service yet so we subscribe and unsubscribe
// both here unnecessarily. but I believe that probably is a theoretical problem and never happen in real life.
// and even if that happens, it will be just a perf hit
if (_fileChangeCookie != s_none)
if (_fileChangeCookie == s_none)
{
var hr = _fileChangeService.UnadviseFileChange(_fileChangeCookie.Value);
return;
}
var fileChangeCookie = _fileChangeCookie.Value;
_fileChangeCookie = s_none;
// Verify if the file still exists before reporting the unadvise failure.
// This is a workaround for VSO #248774
if (hr != VSConstants.S_OK && File.Exists(_filePath))
// We may have tried to subscribe but failed, so have to check a second time
if (fileChangeCookie.HasValue)
{
try
{
Marshal.ThrowExceptionForHR(
_fileChangeService.UnadviseFileChange(fileChangeCookie.Value));
}
catch (Exception e) when (ShouldTrapException(e))
{
Marshal.ThrowExceptionForHR(hr);
}
_fileChangeCookie = s_none;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册