Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First-chance exceptions when writing UsedReferences.log #89

Closed
KirillOsenkov opened this issue Mar 8, 2024 · 5 comments
Closed

First-chance exceptions when writing UsedReferences.log #89

KirillOsenkov opened this issue Mar 8, 2024 · 5 comments

Comments

@KirillOsenkov
Copy link
Contributor

When the analyzer runs (pretty much on every keystroke) it fails with this exception because the file is locked:

System.IO.IOException: The process cannot access the file 'C:\temp\wpf\obj\Debug\net472\_ReferenceTrimmer_UsedReferences.log' because it is being used by another process.
   at void System.IO.__Error.WinIOError(int errorCode, string maybeFullPath)
   at void System.IO.FileStream.Init(string path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, string msgPath, bool bFromProxy, bool useLongPath, bool checkHost)
   at new System.IO.FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy, bool useLongPath, bool checkHost)
   at Stream System.IO.StreamWriter.CreateFile(string path, bool append, bool checkHost)
   at new System.IO.StreamWriter(string path, bool append, Encoding encoding, int bufferSize, bool checkHost) x 2
   at void System.IO.File.WriteAllLines(string path, IEnumerable<string> contents)
   at void ReferenceTrimmer.Analyzer.ReferenceTrimmerAnalyzer.DumpUsedReferences(CompilationAnalysisContext context) in D:/a/ReferenceTrimmer/ReferenceTrimmer/src/Analyzer/ReferenceTrimmerAnalyzer.cs:line 85
   at void Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteCompilationActions(ImmutableArray<CompilationAnalyzerAction> compilationActions, DiagnosticAnalyzer analyzer, CompilationEvent compilationEvent, CancellationToken cancellationToken)+((Action<CompilationAnalysisContext> action, CompilationAnalysisContext context) data) => { } in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs:line 332
   at void Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock<TArg>(DiagnosticAnalyzer analyzer, Action<TArg> analyze, TArg argument, AnalysisContextInfo? info, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs:line 1177
   at void Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows<TArg>(DiagnosticAnalyzer analyzer, Action<TArg> analyze, TArg argument, AnalysisContextInfo? contextInfo, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs:line 1161
   at void Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteCompilationActions(ImmutableArray<CompilationAnalyzerAction> compilationActions, DiagnosticAnalyzer analyzer, CompilationEvent compilationEvent, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs:line 322
   at void Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ExecuteCompilationActions(ImmutableArray<ValueTuple<DiagnosticAnalyzer, ImmutableArray<CompilationAnalyzerAction>>> compilationActionsMap, CompilationEvent compilationEvent, AnalysisScope analysisScope, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs:line 1939
   at async ValueTask<EventProcessedState> Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.TryProcessEventCoreAsync(CompilationEvent compilationEvent, AnalysisScope analysisScope, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs:line 1730
   at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult>.Start<TStateMachine>(ref TStateMachine stateMachine)
   at ValueTask<EventProcessedState> Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.TryProcessEventCoreAsync(CompilationEvent compilationEvent, AnalysisScope analysisScope, CancellationToken cancellationToken)
   at async Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ProcessEventAsync(CompilationEvent e, AnalysisScope analysisScope, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs:line 1629
   at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<TStateMachine>(ref TStateMachine stateMachine)
   at Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ProcessEventAsync(CompilationEvent e, AnalysisScope analysisScope, CancellationToken cancellationToken)
   at async Task<CompilationCompletedEvent> Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ProcessCompilationEventsCoreAsync(AnalysisScope analysisScope, bool prePopulatedEventQueue, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs:line 1612
   at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult>.Start<TStateMachine>(ref TStateMachine stateMachine)
   at Task<CompilationCompletedEvent> Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ProcessCompilationEventsCoreAsync(AnalysisScope analysisScope, bool prePopulatedEventQueue, CancellationToken cancellationToken)
   at async Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ProcessCompilationEventsAsync(AnalysisScope analysisScope, bool prePopulatedEventQueue, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs:line 1547
   at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<TStateMachine>(ref TStateMachine stateMachine)
   at Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ProcessCompilationEventsAsync(AnalysisScope analysisScope, bool prePopulatedEventQueue, CancellationToken cancellationToken)
   at async Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ExecutePrimaryAnalysisTaskAsync(AnalysisScope analysisScope, bool usingPrePopulatedEventQueue, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs:line 697
   at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<TStateMachine>(ref TStateMachine stateMachine)
   at Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.ExecutePrimaryAnalysisTaskAsync(AnalysisScope analysisScope, bool usingPrePopulatedEventQueue, CancellationToken cancellationToken)
   at async Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.AttachQueueAndProcessAllEventsAsync(AsyncQueue<CompilationEvent> eventQueue, AnalysisScope analysisScope, CancellationToken cancellationToken) in C:/Roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs:line 641
   at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<TStateMachine>(ref TStateMachine stateMachine)
   at Task Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver.AttachQueueAndProcessAllEventsAsync(AsyncQueue<CompilationEvent> eventQueue, AnalysisScope analysisScope, CancellationToken cancellationToken)
   at async Task Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.ComputeAnalyzerDiagnosticsAsync(AnalysisScope analysisScope, CancellationToken cancellationToken)+attachQueueAndProcessAllEventsAsync(?)
   at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<TStateMachine>(ref TStateMachine stateMachine)
   at Task Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.ComputeAnalyzerDiagnosticsAsync(AnalysisScope analysisScope, CancellationToken cancellationToken)+attachQueueAndProcessAllEventsAsync(ArrayBuilder<ValueTuple<AnalysisScope, ImmutableArray<CompilationEvent>>> builder, AnalyzerDriver driver, CancellationToken cancellationToken)
   at async Task Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.ComputeAnalyzerDiagnosticsAsync(AnalysisScope analysisScope, CancellationToken cancellationToken)
@KirillOsenkov
Copy link
Contributor Author

If I understand correctly this is writing to the file which was passed as an additional file to the analyzer.

Unfortunately this is problematic as it can lead to problems with analyzers rerunning when the file has changed. Roslyn workspace monitors all files that are input to the compilation for changes on disk, and when they change it retriggers analyzers to feed them the latest inputs. When you write to an input file Roslyn workspace may see this change and if it happens outside the throttling window it will retrigger the analyzer.

In general I understand why this is designed as an analyzer (to tap into the Roslyn world to get the accurate info about references), however it's perhaps undesirable that this runs pretty much on every keystroke in the IDE. Is this an incremental analyzer?

@dfederm
Copy link
Owner

dfederm commented Mar 8, 2024

Interesting. This issue was likely introduced in #81.

This is not really intended to be an incremental analyzer. I would not mind if we only ran it on "real" builds. Do you know if there is an easy way to detect this?

@KirillOsenkov
Copy link
Contributor Author

yes, it feels like this should be a command-line/batch tool, not an interactive tool. Perhaps we can have it disabled by default and only add the analyzer if a property is set? and have people only set that in CI?

@KirillOsenkov
Copy link
Contributor Author

as a short term workaround we can add a Mutex or a lock around File.WriteAllText and have the whole thing in a try/catch

@dfederm
Copy link
Owner

dfederm commented Mar 27, 2024

Fixed by #90

@dfederm dfederm closed this as completed Mar 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants