runtime: plugins fail to load for dotnet 6 single file - self contained app

Description

Running plugins with dotnet 6 rc1 for single file, self contained applications broke. The issue was found originally in Linux, but was also reproduced on windows. Specifically the AssemblyDependencyResolver’s constructor throws an exception when loading the plugin.

To reproduce follow the instructions on the readme in this isolated reproduction of the issue: https://github.com/freddyrios/pluginsloadfailure.

Alternatively follow microsoft documentation on creating an application with plugins https://docs.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support and publish it as a single file, self contained app with the runtime identifier that matches your system.

Configuration

dotnet --version: 6.0.100-rc.1.21463.6 reproduced both on windows 10 and raspbian (linux / debian) windows 10 was x64 and raspbian is arm doesn’t look specific to the OS or architecture

Regression?

It is a regression, see the demo which shows doing the same steps with a different target breaks.

Other information

This is the stacktrace:

System.InvalidOperationException: Cannot load hostpolicy library. AssemblyDependencyResolver is currently only supported if the runtime is hosted through hostpolicy library. —> System.EntryPointNotFoundException: Entry point was not found. at Interop.HostPolicy.corehost_set_error_writer(IntPtr errorWriter) at System.Runtime.Loader.AssemblyDependencyResolver…ctor(String componentAssemblyPath) — End of inner exception stack trace — at System.Runtime.Loader.AssemblyDependencyResolver…ctor(String componeyntAssemblyPath) at AppWithPlugin.PluginLoadContext…ctor(String pluginPath) in [redacted]\pluginsloadfailure\AppWithPlugin\PluginLoadContext.cs:line 13 at AppWithPlugin.Program.LoadPlugin(String relativePath) in [redacted]\pluginsloadfailure\AppWithPlugin\Program.cs:line 71 at AppWithPlugin.Program.<>c.<Main>b__0_0(String pluginPath) in [redacted]\pluginsloadfailure\AppWithPlugin\Program.cs:line 29 at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.ToList() at AppWithPlugin.Program.Main(String[] args) in [redacted]\pluginsloadfailure\AppWithPlugin\Program.cs:line 16

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (12 by maintainers)

Commits related to this issue

Most upvoted comments

I have tested @freddyrios’ application and can confirm that fix is available in 6.0.0-rtm.21511.12 (but not rc2), downloaded from https://github.com/dotnet/installer#installers-and-binaries (second column in the table). The app does not throw missing entrypoint exception for corehost_set_error_writer anymore.

Note that rc2 is not getting the recent runtime changes, use rtm daily snapshots for the latest of net6.

The fix will make it to 6.0 release.

Are there any additional steps needed to ensure it makes it to the full release, or is the presence in the daily snapshots already confirmation it will make it?

Just clarifying if you used the Release/6.0.1XX daily snapshots, then yes, those are builds which will eventually become the final release. (Not the main/7.0.x).

ps. I assume daily snapshots are not covered by the golive

No, the only golive releases are the RC1 and RC2 official builds (and then the final release).

I prepared a fix and sent it to your PR via another PR https://github.com/VSadov/runtime/pull/3.

Most likely reason for the failure is indeed missing PInvoke overrides. We override known PInvokes in system libraries (like System.IO.Compression.Native) so they end up calling embedded implementations, but not in Interop.HostPolicy. It looks like we just missed that we have internal PInvokes there too.

I will work on a fix. It should not be too involved.

It does indeed work on .net 5 - interesting…

The theory is that in both cases the hostpolicy is part of the host/superhost, and since it seems the DllImport fails, it’s probably because we don’t correctly “Redirect” the PInvoke “inside”.

This was the case already in .NET 5, but maybe something else changed.

This will be much easier to solve for @VSadov because he knows exactly how this works…

$ dotnet publish HelloPlugin -c Release -f net6.0 -o test
$ dotnet publish AppWithPlugin -c Release --use-current-runtime --self-contained -p:PublishSingleFile=true -f net6.0 -o test
$ test/AppWithPlugin

Loading commands from: /home/am11/projects/pluginsloadfailure/HelloPlugin.dll
System.InvalidOperationException: Cannot load hostpolicy library. AssemblyDependencyResolver is currently only supported if the runtime is hosted through hostpolicy library.
 ---> System.EntryPointNotFoundException: Unable to find an entry point named 'corehost_set_error_writer' in shared library 'libhostpolicy'.
   at Interop.HostPolicy.corehost_set_error_writer(IntPtr errorWriter)
   at System.Runtime.Loader.AssemblyDependencyResolver..ctor(String componentAssemblyPath)

corehost_set_error_writer is indeed missing from singlefile host:

$ strings ~/.dotnet6/packs/Microsoft.NETCore.App.Host.linux-musl-x64/6.0.0-rtm.21504.6/runtimes/linux-musl-x64/native/singlefilehost |\
    grep corehost_

corehost_main
corehost_main_with_output_buffer
corehost_initialize
corehost_resolve_component_dependencies
Hostpolicy must be initialized and corehost_main must have been called before calling corehost_resolve_component_dependencies.
corehost_resolve_component_dependencies results: {

vs. 5.0

$ strings ~/.dotnet5/packs/Microsoft.NETCore.App.Host.linux-musl-x64/5.0.10/runtimes/linux-musl-x64/native/singlefilehost |\
    grep corehost_

corehost_resolve_component_dependencies
corehost_main
corehost_load
corehost_set_error_writer
corehost_main_with_output_buffer
corehost_initialize
corehost_unload
corehost_main
corehost_main_with_output_buffer
corehost_initialize
corehost_resolve_component_dependencies
Hostpolicy must be initialized and corehost_main must have been called before calling corehost_resolve_component_dependencies.
corehost_resolve_component_dependencies results: {