-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Race condition in adding DefaultSyntaxValue diagnostics in SourceComplexParameterSymbol #17243
Comments
This refers to the following code: if (_lazyDefaultSyntaxValue == ConstantValue.Unset)
{
var diagnostics = DiagnosticBag.GetInstance();
if (Interlocked.CompareExchange(ref _lazyDefaultSyntaxValue, MakeDefaultExpression(diagnostics, ParameterBinder), ConstantValue.Unset) == ConstantValue.Unset)
{
AddDeclarationDiagnostics(diagnostics);
}
diagnostics.Free();
} |
Trying to understand what the failure mode is here. If you access the ExplicitDefaultConstantValue on a parameter and then try to get declaration diagnostics from the compilation, some diagnostics may be missing? However it still seems like if you force complete the assembly, which happens when you try to get diagnostics via public API, the diagnostics will be present when ForceComplete returns. It's just not obvious to me what expectation is violated here. Hypothetically can't symbols get away with deferring computing diagnostics until later on in ForceComplete? For example, we could delay deciding whether to include |
Talked with @jaredpar a bit about this. It feels like whether this is a bug depends on what guarantees symbols make about whether diagnostics will be present in the compilation after reading specific members on symbols. Tagging @AlekseyTs @cston as well to see if you have any thoughts on this. |
The comment on that bug says the following: // This is a race condition where the thread that loses
// the compare exchange tries to access the diagnostics
// before the thread which won the race finishes adding
// them. https://github.com/dotnet/roslyn/issues/17243 To me a clearer way of stating the problem is the following:
By extension that means that we cannot be guaranteed that all declaration diagnostics are available until all of the threads being used to create declaration diagnostics have completed. I'm unsure if that is or is not the guarantee we wanted to provide. Looking deeper at the code I do believe there is a bug here. Take a look at the content of base.ForceComplete(locationOpt, cancellationToken);
// Force binding of default value.
var unused = this.ExplicitDefaultConstantValue; Generally in I think we need to fix this by changing the code to use a proper |
Adding diagnostics after an Interlocked.CompareExchange is a race condition if the thread which succeeds in setting the default syntax value is paused before it adds the diagnostics and another thread binds without seeing the diagnostics.
The text was updated successfully, but these errors were encountered: