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

AsyncLocal diagnostics, clean slate #16779

Open
wants to merge 86 commits into
base: main
Choose a base branch
from
Open

AsyncLocal diagnostics, clean slate #16779

wants to merge 86 commits into from

Conversation

majocha
Copy link
Contributor

@majocha majocha commented Feb 28, 2024

Just yank the NodeCodeBuilder and replace everything with asyncs, without looking back.

  • Added concurrent diagnostics logging with common error count.
  • Added test for AsyncLocal diagnostics flow in async and sync contexts.

This may be useful info generally:
Removing NodeCode reveals some deadlocks. One in RegisterAndImportReferencedAssemblies when called from FSI, there is also some locking in GraphNode. This is easily fixed with Async.SwitchToThreadPool but not easy to pinpoint the cause, as it happens reliably in CI and not that much locally.
I'm not sure what is the exact difference here but it appears NodeCode wrappers run some continuations asynchronously where standard Async does not.

Copy link
Contributor

github-actions bot commented Feb 28, 2024

❗ Release notes required


✅ Found changes and release notes in following paths:

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/8.0.400.md
vsintegration/src docs/release-notes/.VisualStudio/17.11.md

@majocha majocha closed this Feb 28, 2024
@majocha majocha marked this pull request as ready for review April 29, 2024 19:44
@majocha majocha requested a review from a team as a code owner April 29, 2024 19:44
@psfinaki
Copy link
Member

/run fantomas

Copy link
Contributor

Failed to run fantomas: https://github.com/dotnet/fsharp/actions/runs/8894616544

@majocha
Copy link
Contributor Author

majocha commented Apr 30, 2024

I added one more test to make sure it works with ListParallel. (In use with graph-based type checking).

@psfinaki
Copy link
Member

psfinaki commented May 2, 2024

/run fantomas

Copy link
Contributor

github-actions bot commented May 2, 2024

Failed to run fantomas: https://github.com/dotnet/fsharp/actions/runs/8924428488

CheckDisposed()

// Prevent deadlocks in FSI.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd love to put a more meaningful comment here, but I'm not 100% sure what's going on here and I don't want to misrepresent anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't reproduce the problem that this was supposed to solve. I'll get rid of this and see what happens in CI.


let wrapThreadStaticInfo computation =
async {
let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
Copy link
Contributor Author

Choose a reason for hiding this comment

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

NodeCode does this stacking and unwinding implicitly. Without it, we need to be explicit about it by using functions like CompilationGlobalsScope, UseDiagnistcsLogger etc. Most compiler tasks do use them anyway, so there is little need to alter the existing code.

Copy link
Member

Choose a reason for hiding this comment

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

I thought this was the reason why the AsyncLocal<..> replacement was used, is it not?

Copy link
Contributor Author

@majocha majocha May 6, 2024

Choose a reason for hiding this comment

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

Yes, what I meant was: on the boundary, for example Async.AwaitNodeCode does this wrapping implicitly.

OTOH AsyncLocal context will always pass across continuations.
The argument for using AsyncLocal is that with NodeCode sometimes this wrapping doesn't work correctly:
#16712

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To clarify further, there are two orthogonal things here, as I understand it:

  • Passing loggers between threads in the flow of an async computation. It's what NodeCode / AsyncLocal does.

  • Stacking / unwinding of diagnostics context. This is not really related to async, single threaded compiler tasks can do it. This is generally done explicitly with UseDiagnosticsLogger and such, but incidentally NodeCode does this in AwaitNodeCode, AwaitAsync, so it's possible we rely on this behavior somewhere.

|> NodeCode.AwaitTask
|> Async.AwaitTask

// Prevent deadlocks.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Again, this is something I'd need help with. I understand that the idea is to run this synchronously whenever possible to get better callstacks, but I've observed this often deadlocks in CI tests.

Copy link
Member

Choose a reason for hiding this comment

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

It deadlocked on the semaphore above, or somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It froze the CI tests IIRC, I don't think I ever got to repro this one locally, so this is kind of a black box to me.

@@ -4618,7 +4617,7 @@ type FsiEvaluationSession
unresolvedReferences,
fsiOptions.DependencyProvider
)
|> NodeCode.RunImmediateWithoutCancellation
|> Async.RunSynchronously
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't recall why I changed this to RunSynchronously, probably when fighting with fsi deadlocks.

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

3 participants