-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Forward CancellationToken to methods that can take it #33774
Comments
cc: @marklio |
Estimates:
|
The challenge here is around ensuring we invest enough thought in the design to minimize false positives. It might be more than "small".
Conversely, I would guesstimate that once we've identified the problem (e.g. method XYZ(arg1, arg2, arg3) is being called, you have a cancellation token, and there's an XYZ(arg1, arg2, arg3, cancellation token) overload you could be using instead), fixing it will be fairly straightforward. |
Analyzer heuristic:
Fixer:
|
@bartonjs I would also be wary of fixers in the following "harder to detect" scenarios:
|
This is redundant with microsoft/vs-threading#591, which is likely to get funded soon. Or if your plan is to target all TFMs with these analyzers, I can close ours as redundant with yours. |
There is no .NET 5 requirement. The rules are written to look for the presence of types/methods, not a specific version. |
Good to hear. Note we also proposed a related rule to encourage async methods to take a CancellationToken parameter in the first place: microsoft/vs-threading#394 Regarding our microsoft/vs-threading#591 proposal which is largely redundant with this one, we were not going to limit it to only async methods. I don't know why we would want the behavior talked about here that would only impact async methods. If a sync method takes a Per my blog post on the subject a method may at some point transition to a point where cancellation should no longer apply (it's past the "point of no cancellation") because it can't clean up properly if cancellation were honored. Thoughts? |
My opinion is that analyzers for core BCL APIs should be in-box. And shipping the VS analyzers in-box doesn't make a lot of sense. As Stephen said, the analyzers themselves don't check for specific frameworks. However, you need to build with SDK-style projects in order to get the benefit of these analyzers (and have the .NET 5 SDK installed). |
The .NET 5 SDK requirement is unfortunate, and means that the very earliest people can use these analyzers in a stable form in November, right?
I'd like to discuss this further. We actually already have a backlog item on the fxcop analyzer package to add a dependency on the vs-threading analyzers package. There's nothing VS-specific about them, nor ever will be. We have a separate analyzer package for VS-specific concerns. Also, moving analyzers from vs-threading to roslyn-analyzers has a couple of major downsides:
After discussions with the Roslyn team (@jinujoseph in particular) we came to the conclusion that the best thing would be to add a package reference to the vs-threading analyzers package from With that in mind then, does that change how you feel about any of this? |
This is not a requirement, at least not in any of the conversations I've been a part of. There is still going to be a nuget package, just as there is and has been. Rules that have recently been written are already showing up in the already published nuget package. @mavasani, has this changed?
This is already the case, e.g. both packages have a rule that validates tasks are awaited. Why does vs-analyzers have its own when roslyn-analyzers already has one?
If a method accepts a CancellationToken, and the caller passes in default / CancellationToken.None, I wouldn't want the analyzer to warn. Explicitly passing in default/None is a clear indication of "I'm choosing to propagate something other than the original token". So, to me, I don't see the benefit of that public void FinishWork<T>(
TaskCompletionSource<T> tcs,
Func<CancellationToken, Task<T>> func,
CancellationToken cancellationToken)
{
Task.Run(async () =>
{
try { tcs.SetResult(await func(cancellationToken)); }
catch (Exception e) { tcs.SetException(e); }
});
} the analyzer is going to warn about not flowing a cancellation token as an argument to Task.Run, but "fixing" that by putting
I'm fine with this validating all methods that take a cancellation token. I don't remember where the cited constraint came from. |
As @stephentoub said, it looks like I was likely wrong and the analyzers we'll ship in a standalone NuGet package.
I totally agree with you that we shouldn't be shipping multiple analyzers and fixers for the same area. However, this is the first release where the BCL team is seriously looking into analyzers, so some overlap is unavoidable. But my overarching concern is long term consistency. Moving functionality from higher layers to lower layers almost always results in changes to design and/or naming. We can't meaningfully evolve the BCL when we're asked to preserve naming conventions from higher layers because that will quickly create a mess. To me, analyzers are in the exact same category. If I write a web site on Linux it makes zero sense to see analyzers with any VS naming in them. They should feel and behave like any other analyzer tackling BCL APIs. If we do preserve naming and shipping vehicles, then we're shipping the org chart. It seems to me the right approach is combining forces across all our teams that worked on analyzers and moving them where they belong. Yes, there is some pain with shuffling things around, but long term we're all better off. |
I'm not denying that redundancy already exists. And for the benefit of the wider audience, here is our full list of existing vs-threading analyzers.
We considered that argument, but dismissed it because many methods exist that require a It also doesn't set a clear pattern for 'the point of no cancellation'. If I intentionally start passing Your counter example on Task.Run is a good one though.
The issue description itself: "e.g. in an async method that takes a CancellationToken". And again in @bartonjs's mini-spec further down where it's made much more explicit "Only applies to methods using the async state machine generator". |
@AArnott Since we last talked on those items, FxCop analyzers has taken a backseat and will be superceded by this new analyzer package. Majority of ported legacy FxCop CA analyzers will be disabled by default or switched to an IDE-only suggestions, and new analyzers written by CoreFx team will be enabled by default. We should think the path forward for VS threading analyzers - should these be merged into this same package? Should these continue to exist in their current repo, but just follow the same insertion model as new SDK analyzer assembly and directly install with .NET5 SDK? It might be good to setup a meeting to decide the path forward here. |
@mavasani @terrajobst I like the idea of a meeting to get consensus here. I can see myself supporting a migration of vs-threading analyzers to ... wherever this new home is. But I'd like to understand better what's changing, how existing users can continue to use the analyzers in their new home, and (the hardest one) which of our vs-threading analyzers to move. We've had such meetings at least twice before, and each time the work ended up getting cut to move, copy, or recreate the analyzers. |
FWIW, I'd prefer the default reaction to be "let's fix the existing analyzer" rather than "let's build a duplicative analyzer".
Yup. I still believe explicitly passing in
No, I mean, I don't remember why the issue says that. |
I like that. But when we did this, it wasn't an analyzer. It was a built-in compiler warning. And the compiler team made an intentional choice to not warn in that case because they wanted upgrading compiler versions to not produce a bunch of new warnings in existing code.
That's fine. I'm flexible on that point. I just wanted to share what research and thought had already gone into the area. |
Great.
Sorry, I was typing too quickly earlier... I meant to say "awaited without a ConfigureAwait". That's the functionality I was referring to. That's always been an analyzer (or previously IL-based FxCop rule) rather than a compiler warning. |
I wrote it down because it got said on the call 😄. I think it was just trying to limit work; but if it's already been shown to not be too much work, then the more the merrier. |
Ah, yes. And if/when we consolidate, I imagine our version of that analyzer will just disappear, assuming a comparison shows ours doesn't add anything unique any more. |
Work (CPU) done by the analyzer you mean? (As opposed to work done by a developer implementing the analyzer) |
If it does, we should consolidate, rather than have two 😄 |
Yeah, the CPU-work of finding "compatible" alternatives that take a CancellationToken. (Implicitly using a default value seems pretty mild) ... at least, if it's a rule that we expect to be on by default during CLI compilations. Though it's probably enough noise that we wouldn't even turn it on by default with the "waves". |
The issue has been assigned to me, but I'd like to know if we have green light to start working on this. From the above discussion it's not entirely clear to me what course should we take:
Also, regarding these comments:
It may be helpful/relevant to mention that I recently merged a new Roslyn analyzer that looks for any |
Yes. (There isn't one implemented in vs-threading, just the idea for one.)
Please sync with @marklio. He has a prototype implementation of one. It may not be exactly the direction we want to go, but it might help seed some ideas.
Thanks. I suggest we start with something along the lines of the following:
We may need to tweak this a bit as we go, but my expectation is this will lead to a reasonable balance between false positives and false negatives. |
I synced with Mark and he shared the prototype with me. I'm taking a look to determine how much of the code can be reused for this analyzer. |
Thanks. |
The code has been merged. Reopening because the documentation PR is still being reviewed. |
This roslyn analyzer has been merged as well as its documentation, so we can consider it fixed. |
The rule should try to identify places where a
CancellationToken
should have been passed but wasn't, e.g. in an async method that takes aCancellationToken
, a method is called that has an overload that takes aCancellationToken
but a shorter overload that doesn't take aCancellationToken
was used instead.Category: Reliability
The text was updated successfully, but these errors were encountered: