dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.12k stars 4.04k forks source link

NullReference during rebuild while reporting an error #19354

Open davkean opened 7 years ago

davkean commented 7 years ago

From @jviau on May 5, 2017 19:16

I was rebuilding a my solution and I received an NFE report. This was a one-off error and I am unable to reproduce it since. Opening on this repo since LanguageServiceErrorListProvider is owned by you. If you find this is a CPS issue please send back to me.

Solution:

=====================
5/5/2017 12:05:09 PM
Recoverable
System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.VisualStudio.LanguageServices.Implementation.TaskList.ProjectExternalErrorReporter.ReportError2(String bstrErrorMessage, String bstrErrorId, VSTASKPRIORITY nPriority, Int32 iStartLine, Int32 iStartColumn, Int32 iEndLine, Int32 iEndColumn, String bstrFileName)
   at Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.AbstractProject.Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2.ReportError2(String bstrErrorMessage, String bstrErrorId, VSTASKPRIORITY nPriority, Int32 iStartLine, Int32 iStartColumn, Int32 iEndLine, Int32 iEndColumn, String bstrFileName)
   at Microsoft.VisualStudio.ProjectSystem.VS.Build.LanguageServiceErrorListProvider.<AddMessageCoreAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Build.VsProjectBuildTargetErrorListService.<AddMessagesAsync>d__43.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Build.VsProjectBuildTargetErrorListService.<ProcessQueueAsync>d__42.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.VisualStudio.ProjectSystem.CommonProjectSystemTools.Rethrow(Exception ex)
   at Microsoft.VisualStudio.ProjectSystem.ProjectErrorReporting.<>c__DisplayClass6_0.<SubmitErrorReport>b__0()
   at Microsoft.VisualStudio.ProjectSystem.ExceptionFilter.<>c__DisplayClass2_0.<Guard>b__0()
   at GuardMethodClass.GuardMethod(Func`1 , Func`2 , Func`2 )
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.VisualStudio.LanguageServices.Implementation.TaskList.ProjectExternalErrorReporter.ReportError2(String bstrErrorMessage, String bstrErrorId, VSTASKPRIORITY nPriority, Int32 iStartLine, Int32 iStartColumn, Int32 iEndLine, Int32 iEndColumn, String bstrFileName)
   at Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.AbstractProject.Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2.ReportError2(String bstrErrorMessage, String bstrErrorId, VSTASKPRIORITY nPriority, Int32 iStartLine, Int32 iStartColumn, Int32 iEndLine, Int32 iEndColumn, String bstrFileName)
   at Microsoft.VisualStudio.ProjectSystem.VS.Build.LanguageServiceErrorListProvider.<AddMessageCoreAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Build.VsProjectBuildTargetErrorListService.<AddMessagesAsync>d__43.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Build.VsProjectBuildTargetErrorListService.<ProcessQueueAsync>d__42.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.VisualStudio.ProjectSystem.CommonProjectSystemTools.Rethrow(Exception ex)
   at Microsoft.VisualStudio.ProjectSystem.ProjectErrorReporting.<>c__DisplayClass6_0.<SubmitErrorReport>b__0()
   at Microsoft.VisualStudio.ProjectSystem.ExceptionFilter.<>c__DisplayClass2_0.<Guard>b__0()
   at GuardMethodClass.GuardMethod(Func`1 , Func`2 , Func`2 )<---

===================

Copied from original issue: dotnet/project-system#2130

davkean commented 7 years ago

@jviau What build is this?

davkean commented 7 years ago

From @jviau on May 8, 2017 19:41

Ah right, suppose that is helpful haha.

Int-Preview channel, build 26502.1-Preview

davkean commented 7 years ago

@heejaechang Is your fix for this in the build above?

heejaechang commented 7 years ago

this was my fix - http://source.roslyn.io/#Microsoft.VisualStudio.LanguageServices/Implementation/TaskList/ProjectExternalErrorReporter.cs,50

but it says NRE, so not sure whether it is same thing or a bit before my fix. dump would help us here to determine.

sharwell commented 7 years ago
  1. It seems possible for _workspace.GetHostProject(_projectId) to return null, but the conditions in which this could occur are not clear to me.
  2. There is a race condition in that method, where if a document is removed from a project at the same time as a diagnostic is getting reported for it, then hostProject.ContainsFile(bstrFileName) could return true followed by hostProject.GetCurrentDocumentFromPath(bstrFileName) returning null.

Based on the stack above I can't tell which of these two cases resulted in the error. @jviau do you remember if you were removing (or renaming) a file at the time, or perhaps removing/closing/renaming a project within a solution?

:memo: This analysis only considers "direct throws". It does not consider NREs assigned to this method as a result of JIT inlining.

jviau commented 7 years ago

@heejaechang unfortunately I can't get a dump file as I can't reproduce it. Probably a very rare race condition as @sharwell mentions.

@sharwell I was rebuilding the solution, no direct interaction with files besides that. It is possible an automatic nuget restore was running in the background though. I believe I had the directory open in vscode also, which can trigger nuget restores itself.

heejaechang commented 7 years ago

@sharwell I believe all these are happening on UI thread. but without repro or dump, hard to say.

jviau commented 7 years ago

I ran into this again following these steps, (but it only happened once).

  1. New .netcore console app.
  2. Edit csproj, change TargetFramework=netcoreapp2.0 to TargetFrameworks=netcoreapp1.1;net46
  3. don't save the project file
  4. Run the console app, triggering the project file to save (triggering a reload) and attempt to build at the same time.
  5. Received the NFE, a project reload dialog, and the build errors dialog.

This is on vsuwpt 25612.0

davkean commented 7 years ago

I suspect this is probably a race condition on our side. I suspect that we tear down the abstract project just before we've reported an error, resulting in your lookup for a project and resulting dereference to null'ref.