runtime: Dependency on System.Runtime.InteropServices.RuntimeInformation causes runtime error for apps targeting net451 on *nix systems (i.e. running on Mono)
Scenario
- Running a
net451
app depending onSystem.Runtime.InteropServices.RuntimeInformation
on OSX/Ubuntu will produce the following exception at runtime:
dotnet -v run -f net451 1 ↵
Telemetry is: Enabled
Project RuntimeServiceOnMono (.NETFramework,Version=v4.5.1) was previously compiled. Skipping compilation.
Running /usr/local/bin/mono --debug /Users/jtluo/Documents/workspace/juntaoluo/tp/RuntimeServiceOnMono/bin/Debug/net451/osx.10.11-x64/RuntimeServiceOnMono.exe
Process ID: 29130
Unhandled Exception:
System.DllNotFoundException: System.Native
at (wrapper managed-to-native) Interop/Sys:GetUnixNamePrivate ()
at Interop+Sys.GetUnixName () [0x00000] in <filename unknown>:0
at System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform (OSPlatform osPlatform) [0x00000] in <filename unknown>:0
at ConsoleApplication.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.DllNotFoundException: System.Native
at (wrapper managed-to-native) Interop/Sys:GetUnixNamePrivate ()
at Interop+Sys.GetUnixName () [0x00000] in <filename unknown>:0
at System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform (OSPlatform osPlatform) [0x00000] in <filename unknown>:0
at ConsoleApplication.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
Example
See repro at https://github.com/JunTaoLuo/RuntimeServiceOnMono. To run the sample, run dotnet restore
and dotnet run -f net451
I understand Mono is not a scenario that’s actively being developed for but we should not be causing a exception like this especially since we intend to use the InteropServices
APIs in often used ASP.NET packages like Logging.
Currently this means that most of our samples and apps cannot run on Mono (full CLR on *nix).
Environment
dotnet --version
:
Microsoft .NET Core Shared Framework Host
Version : 1.0.1-rc3-004312-00
Build : 1db6c07638a70a621b312e78d4dc9fb31a530f2f
mono -V
:
Mono JIT compiler version 4.0.5 ((detached/1d8d582 Tue Oct 20 15:15:33 EDT 2015)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
TLS: normal
SIGSEGV: altstack
Notification: kqueue
Architecture: x86
Disabled: none
Misc: softdebug
LLVM: yes(3.6.0svn-mono-(detached/a173357)
GC: sgen
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 95 (90 by maintainers)
People would like to use Asp.Net Core even where .NET Core cannot run. I would not want to be that person held off from using it to its full potential just because of this.
Maybe for some things. But that abandons the notion that Mono is an alternate implementation of some/most of net46 – which is its entire purpose today.
If you abandon that design, you are leaving behind almost all of Mono’s consumers.
@jkotas I thought the point of “netstandard” was that it would allow people to build different runtimes targeting the same standard.
If Mono is an implementation of “net46” how can it not be expected to be compatible with netstandard libraries compiled against “net46”?
What’s the plan to address this? We just discovered that this package slipped into the desktop C# compiler causing it to no longer run on Mono.
cc @jaredpar and @agocke
For anyone looking for a workaround (on macOS/Darwin at least), here are some notes on getting things working on OS X (and in theory they should work on Ubuntu with little or no modification, but I haven’t tested):
Find your loadable native images (
.dylib
on macOS/Darwin,.so
on Linux). The location depends on what your dev/packaging platform is./usr/local/share/dotnet/shared/Microsoft.NETCore.App/1.0.0
.Make your native image files loadable. The loader function,
dlopen
, is going to probe the filesystem for a file prefixed withlib
. Even if it knows where to find your images, without the prefix,dlopen
will not find them. You have to givedlopen
a little help by choosing one of methods below.System.*.{dylib|so}
tolibSystem.*.{dylib|so}
.dlopen
seelib{FOO}
even though the filesystem only has {FOO}:Notes: On Linux, looks like you’d probably use patchelf instead. For either option, you can automate this process for all your files with a little
awk
fu:[Only if you chose 2.i] Put your native images in
dlopen
’s search path. You have a few choices, and depends on what your ultimate goals are.libSystem.Native.{dylib|so}
files from Step 2 tobin/{config}/{framework}/{platform}/libSystem.Native.{dylib|so}
. Nothing fancy/brute force. Do this for each project. If someone does a clean clone of a repo, or you’re doing stuff in CI, you should really add a pre-compile task to get this done. Be mindful of any tooling/automation that might periodicallyrm -Rf bin/Debug/*
.LD_LIBRARY_PATH
to one or more paths containing your native images. Normally on macOS/Darwin this would beDYLD_LIBRARY_PATH
and it’s ilk (seeman DYLD_LIBRARY_PATH
for the details), but seems Mono fine with either one. I don’t know if they ever plan to change that, so YMMV.Notes
Regardless of your choice in Step 3, only
libuv.{dylib|so}
will make into the published folder. For files likelibSystem.Native
you’ll have to copy that into thepublish
folder yourself…unless you already installed the .NET Core on the machine you’re deploying too. In that case, you could wrap your executable in a simple one-line shell script that looked something like:LD_LIBRARY_PATH=/usr/local/share/dotnet/shared/Microsoft.NETCore.App/1.0.0 mono bin/Debug/net451/osx.10.11-x64/my-app.exe
. If you were to symlinkMicrosoft.NETCore.App/Current
toMicrosoft.NETCore.App/1.0.0
you could reasonably easily update without touching your script. I’m not entirely sure what the best practice/intent is concerning/usr/local/share/dotnet
paths versus~/.nuget
paths.When the above doesn’t work, I’ve also found it helpful to run
brew update && brew upgrade
and if you get errors and warnings, runbrew doctor
to see what needs to get cleaned up. You might also need to runbrew prune
to fix broken symlinks in/usr/local
beforebrew upgrade
will succeed.Instead I’d wrap the actual code from corefx.