-
Notifications
You must be signed in to change notification settings - Fork 528
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
Comments
Additional notes:
|
Thanks for the report! I was able to reproduce this behavior. Steps followed to reproduce
Test case: DllImportLibdl.zip Devices where libdl.so fails to load
Devices where libdl.so loads successfully
Xamarin.Android versions where libdl.so fails to load
(Tested on the Android 7.1 Nougat (API level 25) x86, Google APIs emulator) Xamarin.Android versions where libdl.so loads successfully
(Tested on the Android 7.1 Nougat (API level 25) x86, Google APIs emulator) Debug output for the successful load:
|
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. |
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 VS 16.2 (or MSBuild 16.2) specific. Stack trace:
And here is how
So it uses |
Interesting that it's different Android versions. Monogame is using:
|
Additional investigation notes The issue depends on the libmonosgen-2.0.so and mscorlib.dll versionSteps tested:
Result: The DllImport loaded libdl.so successfully after step 3. |
Occurs on following devices: Doesn't occur on following devices: |
This is a duplicate of: #3311 I'll close my issue in favor of continuing discussion in here. |
@lambdageek Any updates on this? |
Any update on this one? |
Does anyone have a workaround? |
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 |
I think the workaround is to downgrade to Xamarin.Android 9.3 |
Investigation update from the team about a temporary workaround: A temporary workaround has been identified for the scenario of using
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. |
FYI, after an initial test here:
|
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 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:
One caution about this approach is that it will overwrite the existing configuration file for the library if the library comes with one. |
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.
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.
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.
…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.
…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.
…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.
Changes: mono/mono@cc0632e...6434153 Fixes: #3388
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.
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.
I still seem to be experiencing this error in a monoGame app: |
@QuinnBast Try this, use 'dl' instead of "libstdl" as jalbertSyncroTech mentioned above. <configuration>
<dllmap dll="dl" target="__Internal" />
</configuration> |
I've tried adding the |
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. |
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. |
Still facing the same issue with the latest VS for windows. The apk has the Do I have to use the config file with the latest build? |
Hey @brendanzagaeski, could you please help me with this problem? If you need any logs or code link, I can send those. |
@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! |
…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
Steps to Reproduce
System
andSystem.Runtime.InteropServices
.To MainActivity.OnCreate(Bundle), add a dummy invocation of the above (
DLLOpen("foo", 0)
).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:
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
The text was updated successfully, but these errors were encountered: