提交 969e3309 编写于 作者: J Jason Malinowski 提交者: GitHub

Merge pull request #15073 from jasonmalinowski/do-not-use-ivsopenscope-during-shutdown

Don't crash during shutdown if we try creating metadata snapshots
......@@ -21,7 +21,6 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
/// Manages metadata references for VS projects.
/// </summary>
/// <remarks>
/// The references correspond to hierarchy nodes in the Solution Explorer.
/// They monitor changes in the underlying files and provide snapshot references (subclasses of <see cref="PortableExecutableReference"/>)
/// that can be passed to the compiler. These snapshot references serve the underlying metadata blobs from a VS-wide storage, if possible,
/// from <see cref="ITemporaryStorageService"/>.
......@@ -34,29 +33,39 @@ 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);
}
public IEnumerable<ITemporaryStreamStorage> GetStorages(string fullPath, DateTime snapshotTimestamp)
internal IEnumerable<ITemporaryStreamStorage> GetStorages(string fullPath, DateTime snapshotTimestamp)
{
var key = new FileKey(fullPath, snapshotTimestamp);
......@@ -106,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)
......@@ -288,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"/>
......@@ -343,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
......@@ -159,7 +159,7 @@ protected override void Dispose(bool disposing)
{
UnregisterFindResultsLibraryManager();
DisposeVisualStudioDocumentTrackingService();
DisposeVisualStudioServices();
UnregisterAnalyzerTracker();
UnregisterRuleSetEventHandler();
......@@ -213,12 +213,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.
先完成此消息的编辑!
想要评论请 注册