Open AraHaan opened 2 years ago
Tagging subscribers to this area: @vitek-karas, @agocke, @vsadov See info in area-owners.md if you want to be subscribed.
Author: | AraHaan |
---|---|
Assignees: | - |
Labels: | `area-Host` |
Milestone: | - |
Oh yeah, forgot to mention this happens in FDD deployments and the code does not have to be published to trigger it.
What I think it should be changed to:
for (auto& fx_definition : fx_definitions)
{
if (fx_definition->get_name() != "Microsoft.NETCore.App")
{
continue;
}
return *fx_definition;
}
// not found? Return null.
return nullptr;
@AraHaan do you have a repro for this?
I tried locally with an ASP.NET app and it produces a runtimeconfig.json like this by default:
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "7.0.0-preview.5.22301.12"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "7.0.0-preview.5.22303.8"
}
],
Running the app works just fine, looking at the host trace it shows that the host correctly ordered the frameworks:
--- Summary of all frameworks:
framework:'Microsoft.AspNetCore.App', lowest requested version='7.0.0-preview.5.22303.8', found version='7.0.0-preview.5.22303.8', effective reference version='7.0.0-preview.5.22303.8' apply_patches=1, version_compatibility_range=minor, roll_to_highest_version=0, folder=C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\7.0.0-preview.5.22303.8
framework:'Microsoft.NETCore.App', lowest requested version='7.0.0-preview.5.22301.12', found version='7.0.0-preview.5.22301.12', effective reference version='7.0.0-preview.5.22301.12' apply_patches=1, version_compatibility_range=patch, roll_to_highest_version=0, folder=C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.0-preview.5.22301.12
And that it correctly looked for hostpolicy
in the lowest level framework (NETCore.App):
--- Resolving hostpolicy.dll version from deps json [C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.0-preview.5.22301.12\Microsoft.NETCore.App.deps.json]
The code you're referring to relies on couple of assumptions:
Microsoft.NETCore.App
fx_definitions
array from highest to lowest level - the first is always the app (highest) and the last is always the "root" (lowest)The ordering is done in the fx_resolver
, and while a bit complex I guess this line is a good place to point to:
https://github.com/dotnet/runtime/blob/5889de5fd2cb72dab4a1cfbdfb35466ec5a45f13/src/native/corehost/fxr/fx_resolver.cpp#L508
It probably happens because I also use a framework that depends on Microsoft.NETCore.App
and Microsoft.AspNetCore.App
causing it to look for hostpolicy in aspnetcore.
I have pushed what I did to generate the frameworks which my application that fails uses to github:
dotnet build -c Release
and then dotnet pack -c Release
then add artifacts\packages\Release\Shipping
to the nuget feed of a new project)dotnet build -c Release
and then dotnet pack -c Release
and then add artifacts\packages\Release\Shipping
to the nuget feed of a new project)After that in the new project, make sure it has it's own nuget.config to use for packages have the above directories in it's "feeds". Then add these to the project (after running the generated installers for the bitness of the .NET SDK that is the default):
<Sdk Name="Serilog.Sdk" Version="6.0.6" />
<Sdk Name="Microsoft.EntityFrameworkCore.Sdk" Version="6.0.6" />
The reason why I try it this was is due to dotnet store not working for .NET 6+ and I needed a way to share the dependencies between framework dependent applications without having them copied to their output directories so making them into their own shared frameworks was the best option for me.
However in my case the application targets .NET 6 and so all of it's frameworks are using the 6.0.6 servicing of the default frameworks.
Sorry it took me so long...
Can you please share the runtimeconfig.json
for the app and the custom frameworks?
Or even better, can you please grab a host trace when it fails? https://github.com/dotnet/runtime/blob/main/docs/design/features/host-tracing.md#trace-routing (Please note that the host trace contains information about the machine and user, so make sure you're OK to share it publicly)
I was trying to build it locally but it fails to find matching Microsoft.DotNet.Build.Tasks.Installers
package. I must admit I don't understand what the project is trying to do, but it apparently relies on some internal package.
That failure was due to the fact I did not pin a specific version of that installers package and so a tool in it would fail to run because it expects 7.0.0 of the runtime (which does not exist in the stable state currently).
I think I should have pushed an commit to all of those repos that pins it to the last known version that will run with the 6.0.0 runtime.
Edit: It seems I forgot to push that update for the Serilog installers repo I linked above.
Alright pushed update to the Serilog installers, try to git pull
. Also version changed on it as well.
I think the EF repo is still broken...
You are right, I forgot to commit to it as well (or push).
@vitek-karas ok, pushed.
Thanks a lot for your help, I was able to repro this. I created https://github.com/dotnet/runtime/pull/71959 as the in-house repro within our test framework.
Workaround is to change the order of framework dependencies in the two frameworks you create - make it put NETCore.App last (not sure if SDK can do that, maybe you would need to add a post-build step to edit the json).
Ok, I tried the workaround and it seems to not have worked.
This time when I did:
<Sdk Name="[package name]" Version="6.0.6" />
).<Sdk Name="[package name]" Version="6.0.6" />
).<Sdk Name="[package name]" Version="2022.43.0" />
).Into any project (which will reference the AspNetCore framework if it is not referenced) then when I try to run it it will look for the hostpolicy in the AspNetCore framework still for some reason.
The workaround is in the SDKs - so in your case for example Serilog.App. It's runtimeconfig needs to list the Microsoft.NETCore.App
as the last dependency (and all of the others need to do that as well). I tried this locally with the original repro and it "Fixed" it.
Perhaps my attempt to workaround it was not matching what you did. Mind if I can see what you did different to fix it?
I have just now tested a locally built hostfxr with these changes with success to my application that I could not fix locally with this code change:
Looks like get_root_framework
was another option that can fix it ironically.
Regarding the workaround: I changed the Microsoft.EntityFrameworkCore.App.runtimeconfig.json
(the one which is installed into Program Files by your installers) to look like this:
{
"runtimeOptions": {
"tfm": "net6.0",
"frameworks": [
{
"name": "Microsoft.AspNetCore.App",
"version": "6.0.0"
},
{
"name": "Microsoft.NETCore.App",
"version": "6.0.0"
}
],
"configProperties": {
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
"System.Reflection.NullabilityInfoContext.IsSupported": true
}
}
}
So moving the Microsoft.NETCore.App
reference as last.
I changed the Serilog.App
the same way.
With these the app launches without any issues.
Side note: If you're planning to expose these installers publicly I would recommend you rename the frameworks. Currently they look like official Microsoft or Serilog installers which is at least "misleading".
Workaround is to change the order of framework dependencies in the two frameworks you create - make it put NETCore.App last (not sure if SDK can do that, maybe you would need to add a post-build step to edit the json).
Alright I found a way to have the installers for the frameworks to include the patched runtimeconfig files by:
Sdk.props
and Sdk.targets
from Microsoft.NET.Sdk
.After importing Sdk.targets
override GenerateBuildRuntimeConfigurationFiles
that basically copies a manually maintained runtimeconfig.json file:
<!-- override the version specified in Microsoft.NET.Sdk.targets -->
<!-- Work around https://github.com/dotnet/runtime/issues/71027 by adding NETCore.App last in the runtimeconfig file. -->
<!--
There is a problem with the automatically generated runtimeconfig.json
files where it is possible that it can cause the apphost to look for hostpolicy
in the wrong framework directory.
As such we must provide our own runtimeconfig file that gets copied to the
output directory that is manually maintained.
-->
<!-- Caution: Dangerous Hack. -->
<Target
Name="GenerateBuildRuntimeConfigurationFiles"
Condition="'$(GenerateRuntimeConfigurationFiles)' == 'true'"
BeforeTargets="CopyFilesToOutputDirectory">
<Copy
SourceFiles="$(MSBuildThisFileDirectory)runtimeconfig.json"
SkipUnchangedFiles="true"
DestinationFiles="$(ProjectRuntimeConfigFilePath)" />
<!--
For some reason copy creates 2 files instead of just the
copied file with the new name above.
-->
<Delete Files="$(IntermediateOutputPath)runtimeconfig.json" />
</Target>
I consider this to be dangerous as it is possible for one to forget to update it manually.
Side note: If you're planning to expose these installers publicly I would recommend you rename the frameworks. Currently they look like official Microsoft or Serilog installers which is at least "misleading".
Yeah, those names of the frameworks was to demonstrate the issue.
Description
Currently it seems that the apphost looks for hostpolicy in the last framework that is in runtimeconfig which is not true, instead it should hard code it to look in the Microsoft.NETCore.App framework regardless of how many frameworks are in the runtimeconfig.json file.
Reproduction Steps
Have an application that generates an runtimeconfig where Microsoft.NETCore.App does not appear last (in my case the problem happens when aspnetcore is last so it looks in the aspnetcore framework).
Expected behavior
For the AppHost to either ignore runtimeconfig when looking for hostpolicy by hard coding it or for the .NET SDK to always output it last regardless of how many frameworks the application depends on.
Actual behavior
The apphost always looks for the hostpolicy assembly in the framework listed last in runtimeconfig.
Regression?
Not sure.
Known Workarounds
Currently the only option is to manually patch the runtimeconfig to reorder the frameworks listed after building.
Configuration
The code is running on 6.0.6 of the .NET SDK Frameworks.
Windows 11 21H2. Arch: x64 (AMD64) Specifc to config?: I do not think so, other than sdk generated runtimeconfig.json which cannot be bypassed to use a premade runtimeconfig that is manually maintained in the mean time. Not using blazor at all.
Other information
I think the problem lies in the apphost or whatever it is that tries to load hostpolicy.dll. As for the spot in code, I cant point to where the exact line it is failing at as I am not sure myself.