Skip to content

Use HOSTFXR_PATH to resolve native hostfxr#18911

Merged
mateoatr merged 13 commits into
dotnet:mainfrom
mateoatr:sdkCheckDllImport
Aug 10, 2021
Merged

Use HOSTFXR_PATH to resolve native hostfxr#18911
mateoatr merged 13 commits into
dotnet:mainfrom
mateoatr:sdkCheckDllImport

Conversation

@mateoatr
Copy link
Copy Markdown
Contributor

The runtime property HOSTFXR_PATH is set by the muxer when executing an SDK and stores hostfxr's fullpath. Use this property in the NativeWrapper to resolve hostfxr using a fullpath instead of relying on dlopen/LoadLibrary behavior.

This fixes dotnet/runtime#54965.

dotnet sdk check before changes:

System.DllNotFoundException: Unable to load shared library 'hostfxr' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: dlopen(libhostfxr, 1): image not found
   at Microsoft.DotNet.NativeWrapper.Interop.hostfxr_get_dotnet_environment_info(String dotnet_root, IntPtr reserved, hostfxr_get_dotnet_environment_info_result_fn result, IntPtr result_context)
   at Microsoft.DotNet.NativeWrapper.NETBundlesNativeWrapper.GetDotnetEnvironmentInfo(String dotnetExeDirectory) in Microsoft.DotNet.NativeWrapper.dll:token 0x600000f+0x20
   at Microsoft.DotNet.Tools.Sdk.Check.SdkCheckCommand.Execute() in dotnet.dll:token 0x60004fa+0x13
   at Microsoft.DotNet.Cli.DotNetTopLevelCommandBase.RunCommand(String[] args) in dotnet.dll:token 0x60008ca+0x5e
   at Microsoft.DotNet.Tools.Sdk.SdkCommand.Run(String[] args) in dotnet.dll:token 0x60004e8+0x6
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient) in dotnet.dll:token 0x6000933+0x2e8
   at Microsoft.DotNet.Cli.Program.Main(String[] args) in dotnet.dll:token 0x6000931+0x6f

After changes (tested locally on an M1):

.NET SDKs:
Version                         Status                                       
-----------------------------------------------------------------------------
6.0.100-preview.5.21302.13      Patch 6.0.100-preview.6.21355.2 is available.

Try out the newest .NET SDK features with .NET 6.0.100-preview.6.21355.2.

.NET Runtimes:
Name                          Version                       Status                                      
--------------------------------------------------------------------------------------------------------
Microsoft.NETCore.App         6.0.0-preview.5.21301.5       Patch 6.0.0-preview.6.21352.12 is available.
Microsoft.AspNetCore.App      6.0.0-preview.5.21301.17      Patch 6.0.0-preview.6.21352.12 is available.


The latest versions of .NET can be installed from https://aka.ms/dotnet-core-download. For more information about .NET lifecycles, see https://aka.ms/dotnet-core-support.

@ghost
Copy link
Copy Markdown

ghost commented Jul 14, 2021

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs Outdated
Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs Outdated
Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs Outdated
Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs Outdated
Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs Outdated
Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs
@sfoslund
Copy link
Copy Markdown
Member

@mateoatr will there be any changes needed on the SDK side for this?

{
PreloadWindowsLibrary("hostfxr.dll");
}
HostFxrPath = (string)AppContext.GetData("HOSTFXR_PATH");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Check that HostFxrPath? I don't know if the code here can assume that the hosting bits launching it have the HOSTFXR_PATH change.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically it should be able to make that assumption (SDK is bound to a version of runtime), but I agree it would be a good idea to somehow handle the error more gracefully.

Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs
@mateoatr
Copy link
Copy Markdown
Contributor Author

@mateoatr will there be any changes needed on the SDK side for this?

I don't think we need any more changes than the ones in this PR.

Comment on lines +30 to +31
if (!string.IsNullOrEmpty(HostFxrPath))
NativeLibrary.SetDllImportResolver(typeof(Interop).Assembly, HostFxrDllImportResolver);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We might want to fail if he hostfxr path is not available. Mainly because we know it is somewhat random if it will work without the resolver. In short we think this should never happen, but it's better to have diagnostics for this.

Comment on lines +53 to +59
if (libraryName != Constants.HostFxr || !NativeLibrary.TryLoad(HostFxrPath, out IntPtr handle))
return IntPtr.Zero;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here - if it's possible to have some diagnostics... I think it would be better to fail with clear error if we fail to load the library (for whatever reason).

{
return new Command("check", LocalizableStrings.AppFullName);
}
catch (FileNotFoundException e)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems weird that we'd have to catch the exception on just getting the command. I'd expect it to be when the command is actually executed?

Copy link
Copy Markdown
Member

@elinor-fung elinor-fung Aug 4, 2021

Choose a reason for hiding this comment

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

Is this because it is in the static constructor for the Interop class / something else using the class before the command execution?

I think exceptions in static constructors also come through as TypeInitializationException.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It seems weird that we'd have to catch the exception on just getting the command.

Agreed. I moved this to the place where we actually execute the command. Also catching TypeInitializationException now -- I wasn't aware of this.

}
catch (ArgumentException e)
{
throw new GracefulException(string.Format(LocalizableStrings.HostFxrCouldNotBeLoaded, e.Message));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The direct map of FileNotFoundException / ArgumentException to RuntimePropertyNotFound / HostFxrCouldNotBeLoaded also seems unnatural.

  • Could other issues result in FileNotFoundException / ArgumentException?
  • I don't know how I would make the connection between the exceptions caught here and the ones thrown in NativeWrapper Interop

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also, I think the messages are flipped. ArgumentException is being thrown for the runtime property, not loading hostfxr.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Could other issues result in FileNotFoundException / ArgumentException?

Good point. I added a new type of exception for the exceptions related to the hostfxr path resolution thrown in NativeWrapper.Interop. Fixed the messages as well.

@mateoatr mateoatr force-pushed the sdkCheckDllImport branch from 5f225fc to b8e970e Compare August 5, 2021 16:25
Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs Outdated
Copy link
Copy Markdown
Member

@vitek-karas vitek-karas left a comment

Choose a reason for hiding this comment

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

Looks good!

Comment thread src/Cli/dotnet/commands/dotnet-sdk/check/Program.cs Outdated
@mateoatr mateoatr merged commit 5ca6ab9 into dotnet:main Aug 10, 2021
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.

[Preview 4] dotnet sdk check fails when runtimes installed via script

4 participants