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

Synchronize razor compiler assembly loading #11394

Merged
merged 11 commits into from
Jan 23, 2025

Conversation

chsienki
Copy link
Member

This PR ensures that the razor compiler is only loaded a single time between Roslyn and Razor. Whichever succeeds in first loading the assembly will provide their copy to the other.

There is a doc in the first commit that explains the strategy. You should read this before reviewing the rest of the PR.

Note this is blocked on dotnet/roslyn#76752 but it wont require code changes other than updating the roslyn version.

- Add a new ALC that is 'razor compiler' aware
- Atomically load the razor compiler or use a copy already loaded by roslyn
- When creating a new service instance, first load self into the razor alc, then create the service in the razor alc
- This ensures we have full control over how dependencies are resolved.
@chsienki chsienki requested a review from a team as a code owner January 16, 2025 00:56
@chsienki
Copy link
Member Author

@dotnet/razor-compiler and @dotnet/razor-tooling for reviews please :)

else
{
// Roslyn won the race, we need to find the compiler assembly it loaded.
while (true)
Copy link
Member

Choose a reason for hiding this comment

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

You mentioned in the doc that we'd need to error eventually in case Roslyn errored. When does that happen?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thats a good point. When writing the doc, I figured we'd need to do that, but at implementation I realized it's impossible to do so deterministically as-is, as its essentially a halting problem: we don't know if its not-loaded or failed to load and so another Yield might actually succeed. We could stick some arbitrary amount of retries in, but while unlikely, we could still prematurely assume failure if we hit the retry limit because the other thread just didn't get scheduled. We would need to add some other synchronization primitive to roslyn that allows you to query the status of a given assembly load.

The only way we could get into this state where it really has failed to load is if the assembly is missing or corrupted. Roslyn and razor both load the same assembly from disk, so even if we could detect that the load failed in Roslyn, it's just going to fail again in Razor anyway.

Given that its an error case either way, I'm inclined to just update the doc to note this and leave it as-is. If we think that's not acceptable let's file a bug and not block this work on it as its not trivial to do.

Copy link
Member

@davidwengier davidwengier left a comment

Choose a reason for hiding this comment

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

I don't think we need Remote.Razor to target netstandard any more, except possibly for tests. But also don't think its anything for you to worry about in this PR :)

@chsienki
Copy link
Member Author

Moving this to draft while we try a different approach.

@chsienki chsienki marked this pull request as draft January 17, 2025 18:53
@chsienki chsienki marked this pull request as ready for review January 22, 2025 01:55
@chsienki chsienki requested a review from a team as a code owner January 22, 2025 01:55
@chsienki
Copy link
Member Author

@dotnet/razor-compiler this is ready for a second round of reviews. thanks!

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

Successfully merging this pull request may close these issues.

4 participants