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

Cancellable: set token from node/async in features code #16348

Merged
merged 7 commits into from Dec 5, 2023

Conversation

auduchinok
Copy link
Member

@auduchinok auduchinok commented Nov 27, 2023

Rewrites parts of Cancellable.CheckAndThrow. In the original implementation the token was set inside Cancellable.run, which made it work automatically and on a lower level. However, it turned out to be problematic in testing it in more real-world situations, as not all of the FCS checking related code is wrapped in cancellable expressions.

The original implementation maintained list of tokens, which allowed scope-like nesting, so after run the most recent token would be removed. It's a bit different from other thread-static things we have: node code ensures that the proper phase and logger are set/copied before the computations and that the previous state is restored afterwards on the current thread, so subsequent computations start in this state. I've tried to do the same with the list of the cancellation tokens, but it didn't work as good, as I wasn't able to ensure we're clearing the state on the correct thread with the possible thread switching and in parallel node computations.

In this PR I'm making it more similar to the logger/phase logic: we only have one token and set/copy it before/after the computation. This requires setting the token somewhere in the outer code, so, just like the logger/phase, the token is set inside the background compiler, e.g. when starting ParseAndCheckFileInProject and other features.

With this implementation I couldn't yet reproduce access to a module reader without cancellation token being set. The FCS cancellation tests also work as expected. Let's see what does the CI say.

@auduchinok auduchinok requested a review from a team as a code owner November 27, 2023 17:19
@auduchinok
Copy link
Member Author

I'm still thinking about a possibly better approach, but the current changes look promising to me for now to keep testing it. I'm curious about trying to make it lower-level and more automatic for the features code again in future. This could be especially good if node/cancellable/async expressions are unified in service/checker, so only one CE builder would need to know about this token and all the features code would just use it automatically.

@vzarytovskii
Copy link
Member

I'm still thinking about a possibly better approach, but the current changes look promising to me for now to keep testing it. I'm curious about trying to make it lower-level and more automatic for the features code again in future. This could be especially good if node/cancellable/async expressions are unified in service/checker, so only one CE builder would need to know about this token and all the features code would just use it automatically.

Yeah, I'll probably bite the bullet and try to unify them under state-machine based one. In December, when things are a bit more quiet.

Copy link
Contributor

@0101 0101 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a chance we will "leak" a token to some thread and cancel some computation we didn't intend? Do we need to ensure that we call UsingToken at some point before every cancellable computation? I suppose that makes sense, just wondering what if we forget - could we get some rare unexpected cancellations?

src/Compiler/Facilities/BuildGraph.fs Show resolved Hide resolved
@auduchinok
Copy link
Member Author

Is there a chance we will "leak" a token to some thread and cancel some computation we didn't intend?

I can't say for sure whether the token may "leak" to another thread, but it's working in the same way as the logger/phase now. The guard from using a wrong token is setting the token in the top level code, and then node will copy it on the new thread before running the computation.

Do we need to ensure that we call UsingToken at some point before every cancellable computation? I suppose that makes sense, just wondering what if we forget - could we get some rare unexpected cancellations?

Yes, with this change we need to call UsingToken to wrap the FCS computations. And, yes, if we forget to do it somewhere, it may be unexpectedly cancelled. That's why I'd prefer the more automatic approach where it's hidden in the computation implementation, but it's currently more difficult to do as different places use different computation types.

@0101
Copy link
Contributor

0101 commented Nov 29, 2023

I would definitely prefer the automated way also. But wondering what would be a proper way to do it. Even if all computations used the same builder, how would it know when it's time to set the top-level token? We probably don't want to create a new one every time. And we can't check if "it's already there", because that could mean someone else put it on this particular thread. So we'd probably need to ensure that we restore the thread's state whenever we switch out of it? If we could do that that would also take care of any issues with this current approach (if we forget to set it somewhere).

@auduchinok
Copy link
Member Author

But wondering what would be a proper way to do it.

Setting it before the computation and returning the old state after, similar to the previous approach in Cancellable.run, sounds good.

So we'd probably need to ensure that we restore the thread's state whenever we switch out of it? If we could do that that would also take care of any issues with this current approach (if we forget to set it somewhere).

It would be great indeed, but that's what I haven't find a way to do yet, unfortunately. Let's have a call if you want to chat about it more and/or have some ideas to try. 🙂

@auduchinok
Copy link
Member Author

I propose we merge it like this for now, this seems good to try to actually use it. I'll be happy to revisit it when/if there're changes in the builders or around the transparent compiler.

@psfinaki
Copy link
Member

psfinaki commented Dec 5, 2023

Thanks Eugene. Let's get this in :)

@psfinaki psfinaki merged commit d4e3b26 into dotnet:main Dec 5, 2023
26 checks passed
@auduchinok auduchinok deleted the cancellable2 branch December 5, 2023 13:17
0101 added a commit to 0101/fsharp that referenced this pull request Jan 16, 2024
This was referenced Jan 17, 2024
vzarytovskii pushed a commit that referenced this pull request Jan 22, 2024
* Improve AsyncMemoize tests

* relax test condition

* Revert "Cancellable: set token from node/async in features code (#16348)"

This reverts commit d4e3b26.

* remove UsingToken

* remove UsingToken

* test improvement

* relax test condition

* use thread-safe collections when collecting events from AsyncMemoize

* fix flaky test

* release note
psfinaki added a commit that referenced this pull request Jan 25, 2024
* Name resolution: keep type vars in subsequent checks (#16456)

* Keep typars produced in name resolution

* Better debug errors

* Unwrap measure type vars

* Undo check declarations change

* Fix reported range

* Undo occurrence change

* Skip path typars

* Add test

* More freshen typar APIs properly

* Fantomas

* Cleanup

* Add release notes

* 123

---------

Co-authored-by: Vlad Zarytovskii <vzaritovsky@hotmail.com>

* Build benchmarks in CI (#16518)

* Remove profiling startpoint project

* Add bench build job

* Up

* up

* up

---------

Co-authored-by: Kevin Ransom (msft) <codecutter@hotmail.com>

* More ValueOption in compiler: part 1 (#16323)

* More ValueOption in compiler: part 1

* release notes

* Update CheckComputationExpressions.fs

* release notes

* `[Experimental]` `[WIP]` Transparent Compiler (#15179)

* Track CheckDeclarations.CheckModuleSignature activity. (#16534)

* Add Computation Expression Benchmarks (#16541)

* add benchmarks for various usages of CEs

* refactor

* move CE source files to dedicated ce folder

* Update Roslyn to a version which uses Immutable v7 (#16545)

* revert #16326 (addition of XliffTasks reference) (#16548)

* updated devcontainer image (#16551)

* Add higher-order-function-based API for working with untyped AST (#16462)

* Add module-based API for working with untyped AST

* Fantomas

* tryPickUntil → tryPickDownTo

* Don't need that

* Thread path while walking

* Update comment

* Simplify

* Expose `Ast.fold` and `Ast.tryPick`.
* Expose `SyntaxNode.(|Attributes|)`.
* Ensure a few more syntax node cases get hit.

* Update FCS release notes

* Update surface area

* Add back `foldWhile`; add `exists`, `tryNode`

* Put `Ast.foldWhile` back in.

* Add `Ast.exists`.

* Add `Ast.tryNode`.

* `SyntaxTraversal.Traverse` → `Ast.tryPick`…

* Replace uses of `SyntaxTraversal.Traverse` in `FSharpParseFileResults`
  with the appropriate function from the `Ast` module: `exists`,
  `tryPick`, `tryNode`.

* Update surface area

* Need that

* Just to be safe

* Add `Ast.tryPickLast`

* Handle multiple args mid-pipeline

* Before, no signature help was offered in a case like this:

  ```fsharp
  [1..10]
  |> List.fold (fun acc _ -> acc) ‸
  |> List.filter (fun x -> x > 3)
  ```

  The service will now offer help for the `state` parameter when the
  cursor ‸ is in that location.

* `*` instead of error

* `FSharpParseFileResults.TryRangeOfFunctionOrMethodBeingApplied` was
  previously returning the range of the (zero-width)
  `SynExpr.ArbitraryAfterError`. It now returns the range of the `*`
  (`op_Multiply`) instead.

* Update surface area

* Fmt

* Missed in merge

* Add VS release notes entry

* # → ###

* Add 	ryPick tests

* Add a few more tests

* \n

* Bump release notes

* Fmt

* `Ast` → `ParsedInput`

* Use `ParsedInput` as the main AST type.

* Move the `position` parameter rightward.

* Update surface area

* Less `function`

* Update untyped AST docs

* Add basic examples for `ParsedInput` module functions.

* Merge the existing `SyntaxVisitorBase` docs into the new file.

* Clean up doc comments

---------

Co-authored-by: Vlad Zarytovskii <vzaritovsky@hotmail.com>

* Move paren entries to appropriate releases (#16561)

* [main] Update dependencies from dotnet/source-build-reference-packages (#16532)

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240115.2

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24059.3 -> To Version 9.0.0-alpha.1.24065.2

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240116.1

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24059.3 -> To Version 9.0.0-alpha.1.24066.1

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240117.1

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24059.3 -> To Version 9.0.0-alpha.1.24067.1

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240117.1

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24059.3 -> To Version 9.0.0-alpha.1.24067.1

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240117.1

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24059.3 -> To Version 9.0.0-alpha.1.24067.1

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240117.1

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24059.3 -> To Version 9.0.0-alpha.1.24067.1

---------

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Vlad Zarytovskii <vzaritovsky@hotmail.com>

* Attempt to make links from single identifier module names. (#16550)

* Add scenarios where parentheses are around module name.

* Address problem tighter to nameof usage.

* Restore missing commit and inline nameof ident check.

* Add release note entry.

* rewrite SizeOfValueInfo in Optimizer.fs to be tail-recursive (#16559)

* rewrite SizeOfValueInfo in Optimizer.fs to be tail-recursive

* use Brians rewrite into one local function

* stringbuilder is not threadsafe (#16557)

* Array postfix notation in fsharp core api (#16564)

* changed array types to postfix form in all signatures
* changed array types to postfix form in the implementation files

* Revert 16348 (#16536)

* Improve AsyncMemoize tests

* relax test condition

* Revert "Cancellable: set token from node/async in features code (#16348)"

This reverts commit d4e3b26.

* remove UsingToken

* remove UsingToken

* test improvement

* relax test condition

* use thread-safe collections when collecting events from AsyncMemoize

* fix flaky test

* release note

* Small code reshuffle for diff minimization (#16569)

* Moving code around

* Small code reshuffle for diff minimization

* wat

* Refactor parens API (#16461)

* Refactor parens API

* Remove `UnnecessaryParentheses.getUnnecessaryParentheses`.

* Expose `SynExpr.shouldBeParenthesizedInContext`.

* Expose `SynPat.shouldBeParenthesizedInContext`.

* Expose `SyntaxTraversal.TraverseAll`.

* Fantomas

* Use `ParsedInput.fold`

* Tests

* Update surface area

* Clean up sigs & comments

* Update release notes

* Remove redundant async

* Remove stubs (no longer needed)

* Preserve original stacktrace in state machines if available (#16568)

* Preserve original stacktrace in state machines if available

* Update release notes

* Automated command ran: fantomas

  Co-authored-by: vzarytovskii <1260985+vzarytovskii@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* check reportErrors and feature support at top level (#16549)

* Align DU case augmentation with previous behavior in EraseUnions (#16571)

* Align DU case augment with previous behavior in EraseUnions

* Update 8.0.300.md

* modify tests

* Refresh debug surface area (#16573)

* Remove superfluous rec keywords and untangle some functions (#16544)

* remove some superfluous rec keywords and untangle two functions that aren't mutually recursive.

* Don't throw on invalid input in Graph construction (#16575)

* More ValueOption in compiler: part 2 (#16567)

* More ValueOption in complier: part 2

* Update release notes

* extra optimization

* extra optimization 2

* fantomas

* Update dependencies from https://github.com/dotnet/arcade build 20240123.2 (#16579)

Microsoft.DotNet.Arcade.Sdk
 From Version 8.0.0-beta.24060.4 -> To Version 8.0.0-beta.24073.2

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>

* [main] Update dependencies from dotnet/source-build-reference-packages (#16574)

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240122.5

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24067.1 -> To Version 9.0.0-alpha.1.24072.5

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240123.1

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 9.0.0-alpha.1.24067.1 -> To Version 9.0.0-alpha.1.24073.1

---------

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Tomas Grosup <tomasgrosup@microsoft.com>

* Improve AsyncMemoize tests (#16580)

---------

Co-authored-by: Eugene Auduchinok <eugene.auduchinok@gmail.com>
Co-authored-by: Vlad Zarytovskii <vzaritovsky@hotmail.com>
Co-authored-by: Petr <psfinaki@users.noreply.github.com>
Co-authored-by: Kevin Ransom (msft) <codecutter@hotmail.com>
Co-authored-by: Petr Pokorny <petrpokorny@microsoft.com>
Co-authored-by: Florian Verdonck <florian.verdonck@outlook.com>
Co-authored-by: dawe <dawedawe@posteo.de>
Co-authored-by: Tomas Grosup <tomasgrosup@microsoft.com>
Co-authored-by: Martin <29605222+Martin521@users.noreply.github.com>
Co-authored-by: Brian Rourke Boll <brianrourkeboll@users.noreply.github.com>
Co-authored-by: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Jakub Majocha <1760221+majocha@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

5 participants