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

VS 16.2.0 regression: failed DllImport on the libdl system library. #3388

Closed
plynkus opened this issue Jul 25, 2019 · 25 comments · Fixed by #3540
Closed

VS 16.2.0 regression: failed DllImport on the libdl system library. #3388

plynkus opened this issue Jul 25, 2019 · 25 comments · Fixed by #3540
Assignees
Labels
vs-sync For internal use only; creates a VSTS "mirror" issue.

Comments

@plynkus
Copy link

plynkus commented Jul 25, 2019

Steps to Reproduce

  1. Update to the initial VS 16.2.0 release (which includes Xamarin.Android 9.4.0.51).
  2. Create a blank Xamarin.Android application via the appropriate template.
  3. Atop MainActivity.cs, add usings for System and System.Runtime.InteropServices.
  4. To the MainActivity class, add:
        [DllImport("libdl", EntryPoint = "dlopen")]
        private static extern IntPtr DLLOpen(string fileName, int flags);
  1. To MainActivity.OnCreate(Bundle), add a dummy invocation of the above (DLLOpen("foo", 0)).

  2. Build and run.

Expected Behavior

Proper lookup / load of the library, appropriate output pane notification (e.g., the logging reports a series of load errors in search path locations followed by a DllImport loaded library '/system/lib/libdl.so' success indication.

Actual Behavior

The application throws System.DllNotFoundException for libdl and the output logging shows suspicious E/Linker errors:

07-24 18:03:43.058 D/Mono    (20858): DllImport attempting to load: 'libdl'.
07-24 18:03:43.067 D/Mono    (20858): DllImport error loading library '/storage/emulated/0/Android/data/com.companyname.dllimporttest/files/.__override__/libdl': '(null)'.
07-24 18:03:43.073 D/Mono    (20858): DllImport error loading library '/storage/emulated/0/Android/data/com.companyname.dllimporttest/files/.__override__/libdl.so': '(null)'.
07-24 18:03:43.080 D/Mono    (20858): DllImport error loading library '/storage/emulated/0/Android/data/com.companyname.dllimporttest/files/.__override__/libdl.so': '(null)'.
07-24 18:03:43.082 D/Mono    (20858): DllImport error loading library '/system/lib/libdl': '(null)'.
07-24 18:03:43.086 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/Mono.Android.DebugRuntime-1/lib/arm/libmonosgen-32bit-2.0.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.090 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.092 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.095 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.098 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.100 D/Mono    (20858): DllImport error loading library '/system/lib/libdl.so': 'dlopen failed: library "/system/lib/libdl.so" needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace "classloader-namespace"'.
07-24 18:03:43.102 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/Mono.Android.DebugRuntime-1/lib/arm/libmonosgen-32bit-2.0.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.105 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.107 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.109 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.111 E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
07-24 18:03:43.111 D/Mono    (20858): DllImport error loading library '/system/lib/libdl.so': 'dlopen failed: library "/system/lib/libdl.so" needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace "classloader-namespace"'.
07-24 18:03:43.112 D/Mono    (20858): DllImport error loading library 'libdl': '(null)'.
07-24 18:03:43.113 D/Mono    (20858): DllImport error loading library 'libdl.so': '(null)'.
07-24 18:03:43.114 D/Mono    (20858): DllImport error loading library 'libdl.so': '(null)'.
07-24 18:03:43.115 D/Mono    (20858): DllImport error loading library 'libdl': '(null)'.
07-24 18:03:43.115 W/Mono    (20858): DllImport unable to load library '(null)'.
Loaded assembly: System.Runtime.Serialization.dll [External]
**System.DllNotFoundException:** 'libdl'

Version Information

Xamarin.Android SDK 9.4.0.51 (d16-2/9fa7775)
Xamarin.Android Reference Assemblies and MSBuild support.
Mono: mono/mono@e6f5369c2d2
Java.Interop: xamarin/java.interop/d16-2@d64ada5
LibZipSharp: grendello/LibZipSharp/d16-2@caa0c74
LibZip: nih-at/libzip@b95cf3f
ProGuard: xamarin/proguard@905836d
SQLite: xamarin/sqlite@8212a2d
Xamarin.Android Tools: xamarin/xamarin-android-tools/d16-2@6f6c969

VS bug #972238

@plynkus
Copy link
Author

plynkus commented Jul 25, 2019

Additional notes:

  • Identified through an app failure after a first no-change build under the VS 16.2.0 release yesterday.
  • Only target device tested so far is an NVIDIA SHIELD Tablet K1 running Android 7.0 (API 24).
  • Changing the library reference to a random sibling (e.g. libm, which also lives under /system/lib) resulted in a successful load, so this may be something specific to libdl.

@plynkus plynkus changed the title VS 16.2.0 regression: failed DllImport on libdl system library. VS 16.2.0 regression: failed DllImport on the libdl system library. Jul 25, 2019
@brendanzagaeski brendanzagaeski added Area: App Runtime Issues in `libmonodroid.so`. regression labels Jul 28, 2019
@brendanzagaeski
Copy link
Contributor

Thanks for the report! I was able to reproduce this behavior.

Steps followed to reproduce

  1. Build and run the attached test case in the Debug configuration.
  2. Tap the envelope icon in the bottom right of the screen to attempt to run the DLLOpen() method.

Test case: DllImportLibdl.zip

Devices where libdl.so fails to load

  • Android 7.1 Nougat (API level 25) x86, Google APIs emulator
  • Android 7.1 Nougat (API level 25) armeabi-v7a, Motorola Moto E4

Devices where libdl.so loads successfully

  • Android 9.0 Pie (API level 28) x86, Google APIs emulator
  • Android 9.0 Pie (API level 28) arm64-v8a, Google Pixel 3

Xamarin.Android versions where libdl.so fails to load

  • Xamarin.Android SDK 9.4.0.51 (d16-2/9fa7775)
  • Xamarin.Android SDK 9.5.0.27 (d16-3/16c4494)

(Tested on the Android 7.1 Nougat (API level 25) x86, Google APIs emulator)

Xamarin.Android versions where libdl.so loads successfully

  • Xamarin.Android SDK 9.3.0.23 (d16-1/ebd7bda)

(Tested on the Android 7.1 Nougat (API level 25) x86, Google APIs emulator)

Debug output for the successful load:

D/Mono    ( 8616): DllImport attempting to load: 'libdl'.
D/Mono    ( 8616): DllImport error loading library '/storage/emulated/0/Android/data/com.companyname.androidapp1/files/.__override__/libdl': 'dlopen failed: library "/storage/emulated/0/Android/data/com.companyname.androidapp1/files/.__override__/libdl" not found'.
D/Mono    ( 8616): DllImport error loading library '/storage/emulated/0/Android/data/com.companyname.androidapp1/files/.__override__/libdl.so': 'dlopen failed: library "/storage/emulated/0/Android/data/com.companyname.androidapp1/files/.__override__/libdl.so" not found'.
D/Mono    ( 8616): DllImport error loading library '/system/lib/libdl': 'dlopen failed: library "/system/lib/libdl" not found'.
E/linker  ( 8616): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/Mono.Android.DebugRuntime-1/lib/x86/libmonosgen-32bit-2.0.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.androidapp1-1/lib/x86:/data/app/com.companyname.androidapp1-1/base.apk!/lib/x86", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.androidapp1"]
E/linker  ( 8616): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.androidapp1-1/lib/x86/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.androidapp1-1/lib/x86:/data/app/com.companyname.androidapp1-1/base.apk!/lib/x86", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.androidapp1"]
E/linker  ( 8616): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.androidapp1-1/lib/x86/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.androidapp1-1/lib/x86:/data/app/com.companyname.androidapp1-1/base.apk!/lib/x86", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.androidapp1"]
E/linker  ( 8616): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.androidapp1-1/lib/x86/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.androidapp1-1/lib/x86:/data/app/com.companyname.androidapp1-1/base.apk!/lib/x86", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.androidapp1"]
E/linker  ( 8616): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.androidapp1-1/lib/x86/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.androidapp1-1/lib/x86:/data/app/com.companyname.androidapp1-1/base.apk!/lib/x86", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.androidapp1"]
D/Mono    ( 8616): DllImport error loading library '/system/lib/libdl.so': 'dlopen failed: library "/system/lib/libdl.so" needed or dlopened by "/data/app/com.companyname.androidapp1-1/lib/x86/libmonodroid.so" is not accessible for the namespace "classloader-namespace"'.
D/Mono    ( 8616): DllImport error loading library 'libdl': 'dlopen failed: library "libdl" not found'.
D/Mono    ( 8616): DllImport loaded library 'libdl.so'.
D/Mono    ( 8616): DllImport searching in: 'libdl' ('libdl.so').
D/Mono    ( 8616): Searching for 'dlopen'.
D/Mono    ( 8616): Probing 'dlopen'.
D/Mono    ( 8616): Found as 'dlopen'.

@jonpryor jonpryor modified the milestones: Under Consideration, d16-3 Jul 29, 2019
@shimfish
Copy link

I just came across this as well while trying to deploy a build with Monogame from source.

It appears to work on Android 4, 5, 8 and 9 but fails on Android 6 and 7.

@akravch
Copy link

akravch commented Jul 31, 2019

It looks like I have the same issue, or at least it's very close, but the problematic versions are different from the ones @shimfish mentioned:

4.2 - Crash
5.0 - Crash
7.1 - OK
8.0 - OK
8.1 - OK

VS 16.2 (or MSBuild 16.2) specific.

Stack trace:

I/MonoDroid(25049): System.DllNotFoundException: libGLESv2.dll
I/MonoDroid(25049):   at (wrapper managed-to-native) OpenTK.Graphics.ES20.GL+Core.GetIntegerv(OpenTK.Graphics.ES20.GetPName,int*)
I/MonoDroid(25049):   at OpenTK.Graphics.ES20.GL.GetInteger (OpenTK.Graphics.ES20.GetPName pname, System.Int32* params) [0x00000] in <458c50ade00c47e18311a85cab5883df>:0 
I/MonoDroid(25049):   at Monosyne.Platform.Android.AndroidView.get_FrameBufferId () [0x00000] in <a09e67f070664889b61375cdb6bd09fa>:0 
I/MonoDroid(25049):   at Monosyne.Platform.Android.AndroidView.OnSurfaceCreated (Javax.Microedition.Khronos.Opengles.IGL10 gl, Javax.Microedition.Khronos.Egl.EGLConfig config) [0x0002c] in <a09e67f070664889b61375cdb6bd09fa>:0 
I/MonoDroid(25049):   at Android.Opengl.GLSurfaceView+IRendererInvoker.n_OnSurfaceCreated_Ljavax_microedition_khronos_opengles_GL10_Ljavax_microedition_khronos_egl_EGLConfig_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_gl, System.IntPtr native_config) [0x00019] in <627a58f708c445c88e95ff2d80953f78>:0 
I/MonoDroid(25049):   at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.26(intptr,intptr,intptr,intptr)

And here is how OpenTK.Graphics.ES20.GL+Core.GetIntegerv is defined:

[SuppressUnmanagedCodeSecurity]
[DllImport("libGLESv2.dll", EntryPoint = "glGetIntegerv")]
internal static extern unsafe void GetIntegerv(GetPName pname, [Out] int* @params);

So it uses [DllImport] as well.

@shimfish
Copy link

shimfish commented Jul 31, 2019

Interesting that it's different Android versions.

Monogame is using:

[DllImport("dl")]
public static extern IntPtr dlopen(string path, int flags);

@brendanzagaeski
Copy link
Contributor

Additional investigation notes

The issue depends on the libmonosgen-2.0.so and mscorlib.dll version

Steps tested:

  1. Build and deploy using Xamarin.Android SDK 9.4.0.51 (d16-2/9fa7775).
  2. Reconfirm the error.
  3. Push libmonosgen-2.0.so and mscorlib.dll from Xamarin.Android SDK 9.3.0.23 (d16-1/ebd7bda) to the test app's files/.__override__ directory.

Result:

The DllImport loaded libdl.so successfully after step 3.

@AndreCL
Copy link

AndreCL commented Aug 9, 2019

Occurs on following devices:
Motorola Moto G4 Play w. Android 6.0
LGE K3 2017 w. Android 6.0
Motorola Moto Z w. Android 7.0
Huawei Mate 9 w. Android 7.0

Doesn't occur on following devices:
Samsung Galaxy S9 w. Android 8.0
Google Pixel 2 w. Android 8.1
Sony Xperia XZ1 Compact w. Android 8.0
Nokia 1 w. Android 8.1 (Go edition)
Google Pixel 3 w. Android 9
Google Pixel 2 w. Android 9
Samsung Galaxy S9 w. Android 9.0

@harry-cpp
Copy link
Contributor

This is a duplicate of: #3311

I'll close my issue in favor of continuing discussion in here.

@jalbertSyncroTech
Copy link

@lambdageek Any updates on this?

@dsaf
Copy link

dsaf commented Aug 12, 2019

Any update on this one?

@ka1eka
Copy link

ka1eka commented Aug 19, 2019

Does anyone have a workaround?

@plynkus
Copy link
Author

plynkus commented Aug 19, 2019

The code that triggered it in our case was from a Nuget package, but we were able to temporarily ingest the code and make a change. Oddly enough, on the failing device, changing the reference to libm allowed invocations to successfully find dlopen(). Total coincidence that we noticed this when cross checking that the problem was unique to libdl. I didn't look into why this worked and simply ran with it until a proper fix arrives.

@shimfish
Copy link

Does anyone have a workaround?

I think the workaround is to downgrade to Xamarin.Android 9.3

https://github.com/xamarin/xamarin-android#downloads

@brendanzagaeski
Copy link
Contributor

Investigation update from the team about a temporary workaround:

A temporary workaround has been identified for the scenario of using dlopen() from libdl.

  1. Add an application configuration file to the Android app project. (Add a new XML file to the Android app project that matches the assembly with a .dll.config extension. For example, if the assembly name is AndroidApp1, name the file AndroidApp1.dll.config.)

  2. Leave the Build Action of the file as None, and set the Copy to Output Directory property to Copy if newer.

  3. Set the file contents to:

    <configuration>
      <dllmap dll="libdl" target="__Internal" />
    </configuration>

    (If you already have an application configuration file, you can just add the <dllmap> element to it.)

  4. Clean and rebuild the project.

Other investigation notes:

The commit that introduced the change in behavior has been identified as mono/mono@1be343e. The team is moving ahead to correct the change in behavior.

@plynkus
Copy link
Author

plynkus commented Aug 21, 2019

FYI, after an initial test here:

  • This workaround worked for the case where the DllImport declaration, call are in the app itself (per the simple test case in this issue's description).
  • The workaround did not work for our real use case where the DllImport and call are in a third party library employed by the application.

@brendanzagaeski
Copy link
Contributor

brendanzagaeski commented Aug 21, 2019

Ooh shoot. Thanks for checking that! By default, the Xamarin.Android build system only copies configuration that it finds in the same directory as the resolved path of the corresponding assembly.

One approach for a prebuilt library would be to copy a library configuration file alongside the resolved location of the library. For example, for a <PackageReference> style NuGet package, you could put a library configuration file in the appropriate lib\* subdirectory under the %USERPROFILE%\.nuget cache directory

Another option that might be more convenient is to use a custom target to extend the Xamarin.Android build system to copy the library configuration file from the app project during the build:

  1. Add a configuration file to the Android app project that matches the assembly name of the library that has the DllImport. So for example, if the library is AndroidLibrary1, name the file AndroidLibrary1.dll.config.

  2. In this case, it's fine to leave the Build Action as None and Copy to Output Directory as Do not copy. (The custom target in step 4 will take care of the copying instead.)

  3. As before, set the file contents to:

    <configuration>
      <dllmap dll="libdl" target="__Internal" />
    </configuration>
  4. Open the Android app project .csproj file in a text editor, and add the following custom target to the end of the file, just before the closing </Project> tag:

    <PropertyGroup>
      <AfterGenerateAndroidManifest>
        $(AfterGenerateAndroidManifest);
        CopyExtraConfigFiles;
      </AfterGenerateAndroidManifest>
    </PropertyGroup> 
    <Target Name="CopyExtraConfigFiles">
      <CopyIfChanged
          SourceFiles="AndroidLibrary1.dll.config"
          DestinationFiles="$(MonoAndroidIntermediateAssemblyDir)AndroidLibrary1.dll.config" />
    </Target>

    Be sure to replace AndroidLibrary1.dll.config in the SourceFiles and DestinationFiles parameters with the file name from steps 1–3.

  5. Clean and rebuild the project.

One caution about this approach is that it will overwrite the existing configuration file for the library if the library comes with one.

lambdageek added a commit to lambdageek/mono that referenced this issue Aug 21, 2019
The intention of calling `g_file_test (file, G_FILE_TEST_EXISTS)` where file is
the name of a shared library we want to open is to speed up probing for
non-existent libraries.

See mono#12074

The problem is that if file is just a simple "libdl.so" then `dlopen (file)`
doesn't just look for it in the current working directory, it will probe some
other paths too.  (For example on desktop linux you'd also look in all the
directories in LD_LIBRARY_PATH).  So the g_file_test() call is not a robust way
to avoid calling dlopen if the filename is relative.

But it actually broke more things: dotnet/android#3388

When probing for "libdl.so" on Android mono_lookup_pinvoke_call will first try
prepending some paths that it knows about and we end up calling
`dlopen ("/system/lib/libdl.so")` which will fail because Bionic has security
restrictions on what code can dlopen something from /system/lib with an
absolute path.  Eventually mono_lookup_pinvoke_call will go back to trying the
bare "libdl.so" which hits `g_file_test` and returns NULL.

The new code only does the file test if we pass it an absolute path, which
gives Bionic's dlopen a chance to deal with relative paths however it needs to.
monojenkins pushed a commit to monojenkins/mono that referenced this issue Aug 21, 2019
The intention of calling `g_file_test (file, G_FILE_TEST_EXISTS)` where file is
the name of a shared library we want to open is to speed up probing for
non-existent libraries.

See mono#12074

The problem is that if file is just a simple "libdl.so" then `dlopen (file)`
doesn't just look for it in the current working directory, it will probe some
other paths too.  (For example on desktop linux you'd also look in all the
directories in LD_LIBRARY_PATH).  So the g_file_test() call is not a robust way
to avoid calling dlopen if the filename is relative.

But it actually broke more things: dotnet/android#3388

When probing for "libdl.so" on Android mono_lookup_pinvoke_call will first try
prepending some paths that it knows about and we end up calling
`dlopen ("/system/lib/libdl.so")` which will fail because Bionic has security
restrictions on what code can dlopen something from /system/lib with an
absolute path.  Eventually mono_lookup_pinvoke_call will go back to trying the
bare "libdl.so" which hits `g_file_test` and returns NULL.

The new code only does the file test if we pass it an absolute path, which
gives Bionic's dlopen a chance to deal with relative paths however it needs to.
monojenkins pushed a commit to monojenkins/mono that referenced this issue Aug 21, 2019
The intention of calling `g_file_test (file, G_FILE_TEST_EXISTS)` where file is
the name of a shared library we want to open is to speed up probing for
non-existent libraries.

See mono#12074

The problem is that if file is just a simple "libdl.so" then `dlopen (file)`
doesn't just look for it in the current working directory, it will probe some
other paths too.  (For example on desktop linux you'd also look in all the
directories in LD_LIBRARY_PATH).  So the g_file_test() call is not a robust way
to avoid calling dlopen if the filename is relative.

But it actually broke more things: dotnet/android#3388

When probing for "libdl.so" on Android mono_lookup_pinvoke_call will first try
prepending some paths that it knows about and we end up calling
`dlopen ("/system/lib/libdl.so")` which will fail because Bionic has security
restrictions on what code can dlopen something from /system/lib with an
absolute path.  Eventually mono_lookup_pinvoke_call will go back to trying the
bare "libdl.so" which hits `g_file_test` and returns NULL.

The new code only does the file test if we pass it an absolute path, which
gives Bionic's dlopen a chance to deal with relative paths however it needs to.
lambdageek added a commit to mono/mono that referenced this issue Aug 22, 2019
…16387)

The intention of calling `g_file_test (file, G_FILE_TEST_EXISTS)` where file is
the name of a shared library we want to open is to speed up probing for
non-existent libraries.

See #12074

The problem is that if file is just a simple "libdl.so" then `dlopen (file)`
doesn't just look for it in the current working directory, it will probe some
other paths too.  (For example on desktop linux you'd also look in all the
directories in LD_LIBRARY_PATH).  So the g_file_test() call is not a robust way
to avoid calling dlopen if the filename is relative.

But it actually broke more things: dotnet/android#3388

When probing for "libdl.so" on Android mono_lookup_pinvoke_call will first try
prepending some paths that it knows about and we end up calling
`dlopen ("/system/lib/libdl.so")` which will fail because Bionic has security
restrictions on what code can dlopen something from /system/lib with an
absolute path.  Eventually mono_lookup_pinvoke_call will go back to trying the
bare "libdl.so" which hits `g_file_test` and returns NULL.

The new code only does the file test if we pass it an absolute path, which
gives Bionic's dlopen a chance to deal with relative paths however it needs to.
lambdageek pushed a commit to mono/mono that referenced this issue Aug 22, 2019
…16392)

The intention of calling `g_file_test (file, G_FILE_TEST_EXISTS)` where file is
the name of a shared library we want to open is to speed up probing for
non-existent libraries.

See #12074

The problem is that if file is just a simple "libdl.so" then `dlopen (file)`
doesn't just look for it in the current working directory, it will probe some
other paths too.  (For example on desktop linux you'd also look in all the
directories in LD_LIBRARY_PATH).  So the g_file_test() call is not a robust way
to avoid calling dlopen if the filename is relative.

But it actually broke more things: dotnet/android#3388

When probing for "libdl.so" on Android mono_lookup_pinvoke_call will first try
prepending some paths that it knows about and we end up calling
`dlopen ("/system/lib/libdl.so")` which will fail because Bionic has security
restrictions on what code can dlopen something from /system/lib with an
absolute path.  Eventually mono_lookup_pinvoke_call will go back to trying the
bare "libdl.so" which hits `g_file_test` and returns NULL.

The new code only does the file test if we pass it an absolute path, which
gives Bionic's dlopen a chance to deal with relative paths however it needs to.
lambdageek pushed a commit to mono/mono that referenced this issue Aug 22, 2019
…16393)

The intention of calling `g_file_test (file, G_FILE_TEST_EXISTS)` where file is
the name of a shared library we want to open is to speed up probing for
non-existent libraries.

See #12074

The problem is that if file is just a simple "libdl.so" then `dlopen (file)`
doesn't just look for it in the current working directory, it will probe some
other paths too.  (For example on desktop linux you'd also look in all the
directories in LD_LIBRARY_PATH).  So the g_file_test() call is not a robust way
to avoid calling dlopen if the filename is relative.

But it actually broke more things: dotnet/android#3388

When probing for "libdl.so" on Android mono_lookup_pinvoke_call will first try
prepending some paths that it knows about and we end up calling
`dlopen ("/system/lib/libdl.so")` which will fail because Bionic has security
restrictions on what code can dlopen something from /system/lib with an
absolute path.  Eventually mono_lookup_pinvoke_call will go back to trying the
bare "libdl.so" which hits `g_file_test` and returns NULL.

The new code only does the file test if we pass it an absolute path, which
gives Bionic's dlopen a chance to deal with relative paths however it needs to.
jonpryor added a commit that referenced this issue Aug 22, 2019
brendanzagaeski added a commit to brendanzagaeski/xamarin-android that referenced this issue Aug 23, 2019
Changes: mono/mono@cc0632e...6434153

Fixes: dotnet#3388

As part of this bump, add a `.apk` test for the scenario from
dotnet#3388.  I confirmed
locally that this test failed on an Android 7.1 (API level 25) x86
emulator before the Mono version bump and passed after it.

One caution is that dotnet#3388 does not affect the most recent Android
versions, and the continuous integration builds currently only run the
`.apk` tests on an API level 29 emulator, so this test would have passed
in the CI builds even before the Mono version bump.
@pjcollins pjcollins added the vs-sync For internal use only; creates a VSTS "mirror" issue. label Aug 23, 2019
jonpryor pushed a commit that referenced this issue Aug 23, 2019
Changes: mono/mono@cc0632e...6434153

Fixes: #3388
Context: mono/mono@6434153

As part of this bump, add a **dlopen**(3) test to
`src/Mono.Android/Test`, to ensure that `[DllImport("libdl")]` works.
This used to work in d16-1 but broke in d16-2 due to
mono/mono@6434153d, because -- and this sounds *bizarre*, but here we
are -- `dlopen("libdl.so")` would *work* while
`dlopen("/full/path/to/libdl.so")` would *fail*, because of security
restrictions:

	D/Mono    (20858): DllImport error loading library '/system/lib/libdl.so': 'dlopen failed: library "/system/lib/libdl.so" needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace "classloader-namespace"'.
	E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/Mono.Android.DebugRuntime-1/lib/arm/libmonosgen-32bit-2.0.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
	E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
	E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
	E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
	E/linker  (20858): library "/system/lib/libdl.so" ("/system/lib/libdl.so") needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.companyname.dllimporttest-1/lib/arm:/data/app/com.companyname.dllimporttest-1/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.companyname.dllimporttest"]
	D/Mono    (20858): DllImport error loading library '/system/lib/libdl.so': 'dlopen failed: library "/system/lib/libdl.so" needed or dlopened by "/data/app/com.companyname.dllimporttest-1/lib/arm/libmonodroid.so" is not accessible for the namespace "classloader-namespace"'.

I confirmed locally that this new test failed on an Android 7.1
(API level 25) x86 emulator before the Mono version bump and passed
after the mono bump.

One caution is that #3388 does not affect the most recent Android
versions, and the continuous integration builds currently only run
the `.apk` tests on an API level 29 emulator, so this test would have
passed in the CI builds even before the Mono version bump.
@QuinnBast
Copy link

I still seem to be experiencing this error in a monoGame app: DllImportError: ‘dl’ (Which comes from libdl) even after trying the workaround mentioned above.

@anthonyhan
Copy link

anthonyhan commented Sep 3, 2019

I still seem to be experiencing this error in a monoGame app: DllImportError: ‘dl’ (Which comes from libdl) even after trying the workaround mentioned above.

@QuinnBast Try this, use 'dl' instead of "libstdl" as jalbertSyncroTech mentioned above.

<configuration>
  <dllmap dll="dl" target="__Internal" />
</configuration>

@QuinnBast
Copy link

I've tried adding the .dll.config file to my project root as well as within the bin folder next to the compiled dll and neither seem to have resolved the issue. We're completely stumped on this one

@brendanzagaeski
Copy link
Contributor

A new Preview version has now been published that includes a fix for this item. The fix is not yet included in a Release version. I will update this issue again when a Release version is available that includes the fix.

Fix included in Xamarin.Android 10.0.0.40.

Fix included on Windows in Visual Studio 2019 version 16.3 Preview 3. To try the Preview version that includes the fix, check for the latest updates in Visual Studio Preview.

Fix included on macOS in Visual Studio 2019 for Mac version 8.3 Preview 3. To try the Preview version that includes the fix, check for the latest updates on the Preview updater channel.

@brendanzagaeski
Copy link
Contributor

A new Release version has now been published that includes the fix for this item.

Fix included in Xamarin.Android 10.0.0.43

Fix included on Windows in Visual Studio 2019 version 16.3. To get the new version that includes the fix, check for the latest updates or install the latest version from https://visualstudio.microsoft.com/downloads/.

Fix included on macOS in Visual Studio 2019 for Mac version 8.3. To get the new version that includes the fix, check for the latest updates on the Stable updater channel.

I also did a quick local check with these versions to make sure I could still reproduce the original problem before the update and could no longer reproduce the problem after the update.

@ravinderjangra
Copy link

ravinderjangra commented Oct 16, 2019

Still facing the same issue with the latest VS for windows. The apk has the .so files but when running the code, I am getting DllNotFoundException. Checked VS for mac as well, same issue.

Do I have to use the config file with the latest build?

@ravinderjangra
Copy link

Hey @brendanzagaeski, could you please help me with this problem? If you need any logs or code link, I can send those.

@brendanzagaeski
Copy link
Contributor

@ravinderjangra, when you get a chance, if you could submit a new issue to describe what you're seeing so the team can take a look, that would be perfect. Thanks for your patience!

ManickaP pushed a commit to ManickaP/runtime that referenced this issue Jan 20, 2020
…ono/mono#16387)

The intention of calling `g_file_test (file, G_FILE_TEST_EXISTS)` where file is
the name of a shared library we want to open is to speed up probing for
non-existent libraries.

See mono/mono#12074

The problem is that if file is just a simple "libdl.so" then `dlopen (file)`
doesn't just look for it in the current working directory, it will probe some
other paths too.  (For example on desktop linux you'd also look in all the
directories in LD_LIBRARY_PATH).  So the g_file_test() call is not a robust way
to avoid calling dlopen if the filename is relative.

But it actually broke more things: dotnet/android#3388

When probing for "libdl.so" on Android mono_lookup_pinvoke_call will first try
prepending some paths that it knows about and we end up calling
`dlopen ("/system/lib/libdl.so")` which will fail because Bionic has security
restrictions on what code can dlopen something from /system/lib with an
absolute path.  Eventually mono_lookup_pinvoke_call will go back to trying the
bare "libdl.so" which hits `g_file_test` and returns NULL.

The new code only does the file test if we pass it an absolute path, which
gives Bionic's dlopen a chance to deal with relative paths however it needs to.

Commit migrated from mono/mono@e74736a
@ghost ghost locked as resolved and limited conversation to collaborators Jun 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
vs-sync For internal use only; creates a VSTS "mirror" issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.