-
Notifications
You must be signed in to change notification settings - Fork 789
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 in GetProjectOptionsFromScript prevents getting referenced packages #12683
Comments
I don't quite understand the likely nature of the bug from the above
When you say "calculated concurrently" could you indicate which routine or code you think is being executed concurrently for the same script? Also when you say "has been cancelled" do you mean that the cancellation hasn't been effective? Or is it more that a bad failing result (related to cancellation) has been written to the cache? |
@dsyme Yes, please check the stacks on the attached screenshots. 🙂
I think this is what is happening indeed, the cancellation tokens are also captured on the screenshots.
The very last screenshot shows a cached failure to write to a locked file inside an MSBuild task. |
Looks like FSharpDependencyManager is allowing multiple concurrent callers to attempt resolutions within its working directory at the same time |
@KevinRansom Could you take a look at this? I think FSharpDependencyManager needs to be made concurrency safe - not its data structures, but rather its use of the working directory as a dedicated non-concurrent resource. |
I shall take a look. For sure there is no real reason beyond debuggability that we reuse the working directory. Although, when trying to figure out what is going on, that is my go to. |
I suppose a risk of using separate directories (ie fixing this bug) is that we will end up spawning hundreds of resolutions as the programmer is editing the references of a script, each typing of a character doing a new spawn. Right now the bug is probably gating the process of doing resolutions in some way. Equally we've gradually moved away from have FSharp.Compiler.Service manage resources and act as a mini-operating-system (e.g. by removing the reactor thread), but it's something to be aware of and watch for. |
It should only create new directories/files for unique dependency provider keys, so it won't be happening for each keystroke, unless changing the reference directives:
And when changing the directives, it currently may reuse the files, leading to hard-to-diagnose race issues. |
Repro steps:
GetProjectOptionsFromScript
GetProjectOptionsFromScript
again (probably from a different thread)The
GetProjectOptionsFromScript
calls are made usinglock
application to prevent concurrent access.Calling and cancelling it like this may lead to situation where two scrips closures are calculated concurrently, despite one of them has already been cancelled by the callee. Here're two screenshots for different threads, both made while staying on the same breakpoint:
This leads to a situation where both threads try to write a generated file during the package restore. If the file is locked then the restore fails and results with missing package references are added to
cache
insideDependencyProvider
, so all laterGetProjectOptionsFromScript
invocations return failed results for the same compiler directive collection.The build failure details
The cached script closure:
Exception stacktrace:
The text was updated successfully, but these errors were encountered: