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

Don't crash during shutdown if we try creating metadata snapshots

Windows Error Reporting is insisting it's surprisingly common for us
to have a thread trying to create a compilation while Visual Studio
is shutting down and we can't make COM calls anymore. This prevents
that from happening. This is a tactical fix and we'll still let the
rest of metadata snapshot system work normally.
上级 bc0016bd
......@@ -33,25 +33,35 @@ internal sealed partial class VisualStudioMetadataReferenceManager : IWorkspaceS
private readonly MetadataCache _metadataCache;
private readonly ImmutableArray<string> _runtimeDirectories;
private readonly IVsFileChangeEx _fileChangeService;
private readonly IVsXMLMemberIndexService _xmlMemberIndexService;
private readonly IVsSmartOpenScope _smartOpenScopeService;
private readonly ITemporaryStorageService _temporaryStorageService;
internal IVsXMLMemberIndexService XmlMemberIndexService { get; }
/// <summary>
/// The smart open scope service. This can be null during shutdown when using the service might crash. Any
/// use of this field or derived types should be synchronized with <see cref="_readerWriterLock"/> to ensure
/// you don't grab the field and then use it while shutdown continues.
/// </summary>
private IVsSmartOpenScope SmartOpenScopeServiceOpt { get; set; }
internal IVsFileChangeEx FileChangeService { get; }
private readonly ReaderWriterLockSlim _readerWriterLock = new ReaderWriterLockSlim();
internal VisualStudioMetadataReferenceManager(IServiceProvider serviceProvider, ITemporaryStorageService temporaryStorageService)
{
_metadataCache = new MetadataCache();
_runtimeDirectories = GetRuntimeDirectories();
_xmlMemberIndexService = (IVsXMLMemberIndexService)serviceProvider.GetService(typeof(SVsXMLMemberIndexService));
_smartOpenScopeService = (IVsSmartOpenScope)serviceProvider.GetService(typeof(SVsSmartOpenScope));
XmlMemberIndexService = (IVsXMLMemberIndexService)serviceProvider.GetService(typeof(SVsXMLMemberIndexService));
SmartOpenScopeServiceOpt = (IVsSmartOpenScope)serviceProvider.GetService(typeof(SVsSmartOpenScope));
_fileChangeService = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx));
FileChangeService = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx));
_temporaryStorageService = temporaryStorageService;
Debug.Assert(_xmlMemberIndexService != null);
Debug.Assert(_smartOpenScopeService != null);
Debug.Assert(_fileChangeService != null);
Debug.Assert(XmlMemberIndexService != null);
Debug.Assert(SmartOpenScopeServiceOpt != null);
Debug.Assert(FileChangeService != null);
Debug.Assert(temporaryStorageService != null);
}
......@@ -105,16 +115,6 @@ private static ImmutableArray<string> GetRuntimeDirectories()
}).Select(FileUtilities.NormalizeDirectoryPath).ToImmutableArray();
}
internal IVsXMLMemberIndexService XmlMemberIndexService
{
get { return _xmlMemberIndexService; }
}
internal IVsFileChangeEx FileChangeService
{
get { return _fileChangeService; }
}
/// <exception cref="IOException"/>
/// <exception cref="BadImageFormatException" />
internal Metadata GetMetadata(string fullPath, DateTime snapshotTimestamp)
......@@ -287,28 +287,38 @@ private ModuleMetadata CreateModuleMetadata(FileKey moduleFileKey, List<ITempora
private bool TryGetFileMappingFromMetadataImporter(FileKey fileKey, out IMetaDataInfo info, out IntPtr pImage, out long length)
{
// here, we don't care about timestamp since all those bits should be part of Fx. and we assume that
// it won't be changed in the middle of VS running.
var fullPath = fileKey.FullPath;
// We might not be able to use COM services to get this if VS is shutting down. We'll synchronize to make sure this
// doesn't race against
using (_readerWriterLock.DisposableRead())
{
// here, we don't care about timestamp since all those bits should be part of Fx. and we assume that
// it won't be changed in the middle of VS running.
var fullPath = fileKey.FullPath;
info = default(IMetaDataInfo);
pImage = default(IntPtr);
length = default(long);
info = default(IMetaDataInfo);
pImage = default(IntPtr);
length = default(long);
var ppUnknown = default(object);
if (ErrorHandler.Failed(_smartOpenScopeService.OpenScope(fullPath, (uint)CorOpenFlags.ReadOnly, s_IID_IMetaDataImport, out ppUnknown)))
{
return false;
}
if (SmartOpenScopeServiceOpt == null)
{
return false;
}
info = ppUnknown as IMetaDataInfo;
if (info == null)
{
return false;
}
var ppUnknown = default(object);
if (ErrorHandler.Failed(SmartOpenScopeServiceOpt.OpenScope(fullPath, (uint)CorOpenFlags.ReadOnly, s_IID_IMetaDataImport, out ppUnknown)))
{
return false;
}
CorFileMapping mappingType;
return ErrorHandler.Succeeded(info.GetFileMapping(out pImage, out length, out mappingType)) && mappingType == CorFileMapping.Flat;
info = ppUnknown as IMetaDataInfo;
if (info == null)
{
return false;
}
CorFileMapping mappingType;
return ErrorHandler.Succeeded(info.GetFileMapping(out pImage, out length, out mappingType)) && mappingType == CorFileMapping.Flat;
}
}
/// <exception cref="IOException"/>
......@@ -342,5 +352,15 @@ private bool TryGetFileMappingFromMetadataImporter(FileKey fileKey, out IMetaDat
return AssemblyMetadata.Create(
moduleBuilder.ToImmutableAndFree());
}
public void DisconnectFromVisualStudioNativeServices()
{
using (_readerWriterLock.DisposableWrite())
{
// IVsSmartOpenScope can't be used as we shutdown, and this is pretty commonly hit according to
// Windows Error Reporting as we try creating metadata for compilations.
SmartOpenScopeServiceOpt = null;
}
}
}
}
\ No newline at end of file
......@@ -162,7 +162,7 @@ protected override void Dispose(bool disposing)
{
UnregisterFindResultsLibraryManager();
DisposeVisualStudioDocumentTrackingService();
DisposeVisualStudioServices();
UnregisterAnalyzerTracker();
UnregisterRuleSetEventHandler();
......@@ -216,12 +216,14 @@ private void UnregisterFindResultsLibraryManager()
}
}
private void DisposeVisualStudioDocumentTrackingService()
private void DisposeVisualStudioServices()
{
if (_workspace != null)
{
var documentTrackingService = _workspace.Services.GetService<IDocumentTrackingService>() as VisualStudioDocumentTrackingService;
documentTrackingService.Dispose();
_workspace.Services.GetService<VisualStudioMetadataReferenceManager>().DisconnectFromVisualStudioNativeServices();
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册