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

Treat missing .ConfigureAwait(false) as errors (and fix) #633

Merged

Conversation

andyleejordan
Copy link
Contributor

I enabled the new .NET Analyzer for the project and then used an Editor Config rule to treat CA2007 as an error. This diagnostic is for any awaited task that does not have an explicit trailing .ConfigureAwait(false) call, an annoying but very necessary configuration for asynchronous .NET library code (such as OmniSharp).

The bugs caused by these missing calls are strange. In the case of PowerShell Editor Services, an LSP server using OmniSharp and powering the PowerShell Extension for VS Code, it showed up as a hang when the server executed user code that used objects from System.Windows.Forms.

This is because that .NET library sets its own synchronization context, which is exactly where ConfigureAwait(continueOnCapturedContext: false) comes into play. The default value is true which roughly means that the awaited tasks will only run on their own context. So when the context is changed (because of System.Windows.Forms or other code introducing a new synchronization context) the task will never be continued, resulting in this hang. By configuring this to false we allow the tasks to continue regardless of the new context.

See this .NET blog post for more details: https://devblogs.microsoft.com/dotnet/configureawait-faq/

Note that elsewhere in the codebase we've been very careful to set it to false, but we've not been perfect. Treating this diagnostic as an error will allow us to be as perfect as possible about it.

@andyleejordan
Copy link
Contributor Author

I've had users confirm that this change solved PowerShell/vscode-powershell#3394, PowerShell/vscode-powershell#3410, and PowerShell/vscode-powershell#3415. Note that I first applied this change to the PowerShell Editor Services code base in PowerShell/PowerShellEditorServices#1533, which alone did not solve the issue.

The same bug was found and fixed in the past with PowerShell/PowerShellEditorServices#1149 which gave me the idea.

@andyleejordan
Copy link
Contributor Author

Ah, I need to fix the tests too, I guess those didn't build from the build script.

I enabled the new .NET Analyzer for the project and then used an Editor
Config rule to treat CA2007 as an error. This diagnostic is for any
awaited task that does not have an explicit trailing
`.ConfigureAwait(false)` call, an annoying but very necessary
configuration for asynchronous .NET library code (such as OmniSharp).

The bugs caused by these missing calls are strange. In the case of
PowerShell Editor Services, an LSP server using OmniSharp and powering
the PowerShell Extension for VS Code, it showed up as a hang when the
server executed user code that used objects from `System.Windows.Forms`.

This is because that .NET library sets its own synchronization context,
which is exactly where `ConfigureAwait(continueOnCapturedContext:
false)` comes into play. The default value is `true` which roughly means
that the awaited tasks will only run on their own context. So when the
context is changed (because of `System.Windows.Forms` or other code
introducing a new synchronization context) the task will never be
continued, resulting in this hang. By configuring this to `false` we
allow the tasks to continue regardless of the new context.

See this .NET blog post for more details: https://devblogs.microsoft.com/dotnet/configureawait-faq/

Note that elsewhere in the codebase we've been very careful to set it to
false, but we've not been perfect. Treating this diagnostic as an error
will allow us to be as perfect as possible about it.
@andyleejordan andyleejordan force-pushed the andschwa/configure-await branch from af69d4e to 3493200 Compare August 10, 2021 18:12
@codecov
Copy link

codecov bot commented Aug 10, 2021

Codecov Report

Merging #633 (6e23b9b) into master (1969872) will decrease coverage by 0.03%.
The diff coverage is n/a.

❗ Current head 6e23b9b differs from pull request most recent head 3493200. Consider uploading reports for the commit 3493200 to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master     #633      +/-   ##
==========================================
- Coverage   69.37%   69.33%   -0.04%     
==========================================
  Files         257      257              
  Lines       12576    12576              
  Branches      848      848              
==========================================
- Hits         8724     8719       -5     
- Misses       3582     3587       +5     
  Partials      270      270              
Impacted Files Coverage Δ
src/Dap.Client/DebugAdapterClient.cs 96.82% <ø> (ø)
src/Dap.Testing/DebugAdapterProtocolTestBase.cs 100.00% <ø> (ø)
src/JsonRpc/OutputHandler.cs 88.46% <ø> (-6.42%) ⬇️
src/Server/LanguageServer.Shutdown.cs 33.33% <ø> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1969872...3493200. Read the comment docs.

@david-driscoll david-driscoll merged commit 5281160 into OmniSharp:master Aug 10, 2021
@github-actions github-actions bot added the mysterious We forgot to label this label Aug 10, 2021
@andyleejordan andyleejordan deleted the andschwa/configure-await branch August 10, 2021 18:41
@andyleejordan
Copy link
Contributor Author

Hey, it's not mysterious! It's a threading deadlock 😆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mysterious We forgot to label this
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants