-
Notifications
You must be signed in to change notification settings - Fork 533
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
System.DllNotFoundException: libmono-native.so assembly:<unknown assembly> type:<unknown type> member:(null) #4772
Comments
Additional info: Compile Android Target Framework = Android 10.0 (Q). |
@samhouts Could we move this issue to https://github.com/xamarin/xamarin-android/issues and move forward to get more information? |
Here is a full stack trace (logcat) from a Huawei P8 Lite Android API 21. This only happens on some Android API 21 devices.
|
@todorspetkov is |
Yes libmono-native.so is present. The apk works on all Android platforms > SDK 21. |
@todorspetkov I don't have enough information in the previous posts to be sure what's going on, but since it involves a native shared library, I guess that some of those devices lack some native symbols (for one reason or another) which prevents the native library from being loaded by the system. Note that the library is built by the Mono project with NDK against API 16 for 32-bit targets and against API 21 for 64-bit targets so it should work (and it does in a fair amount of tests both Mono and Xamarin.Android run). To further diagnose this, if you have access to a failing device, please follow these steps and post a full logcat record (please issue |
Hm, actually, the steps I pointed out won't work... I've just noticed they're for Android O, Android 5.0 won't have the necessary support. |
However, please enable all the possible logging in your application by issuing the following commands from command line before starting your application: adb shell setprop debug.mono.env "MONO_LOG_LEVEL=debug|MONO_LOG_MASK=dll"
adb shell setprop debug.mono.log default,assembly
adb logcat -c Then make sure to cold start the application and when it crashes, back on the command line, issue adb logcat -d > log.txt And attach the |
The error has been signaled by our users and I have seen it in firebase crashlytics. The stack traces I have included are from Firebase Robo device tests. I do not have a physical device with Android 5.0 where I can set adb shell properties... I will try to get one... |
@todorspetkov I doubt it's just any 5.0 device. Some manufacturers were known to make changes to Android that broke compatibility, but never wholesale, it was always per-model (or sometimes even per Android build) |
Regarding this exception Firebase crashlytics says: 76% Huawei, 92% Android 5 devices... I was able to reproduce the crash in Firebase Test lab Robo on a Huawei P8 Lite API 21... |
@todorspetkov So it looks like some Huawei-specific change that broke things. Were you able to enable the extra logging on that device (if it is even possible using the test lab)? |
I am not able to perform the adb shell operations you suggested in Test Lab. I will have to find a physical device thet crashes... It seems very hard these days to get your hands on a 2016 Huawei device running Android 5 :-). |
It is quite ancient, indeed... :) I'm afraid there's no other way though :( |
By chance I was working today on a different issue that required additional logging, and for that issue I checked if it was possible to set the logging properties via an environment file. That does seem to work, so if Firebase Test Lab Robo provides the
|
I performed these operations and am including the logcat output (quite long) in attachment. web-build_2020-06-10T08-20-36.809Z_iim9-hwALE-H-21-en_US-portrait-logcat.txt |
So, the problem is shown here:
Only this is not true... |
I do not know how or why but we started using Android Material Design and switched the following components from: After these changes the app started working on all Robo Test devices from Android 21 to Android 29... We will be publishing a new release shortly and I will be monitoring Firebase Crashlytics to see whether the problem has really disappeared... |
Unfortunately I am still receiving this crash data for some Android SDK 21/22 devices... |
It's really hard to determine the cause without being able to access the device and the information we currently have appears to point to some problem with Huawei devices. However, I've just seen this issue which appears to be the same problem, but reproducible on an emulator. I'll try to reproduce it locally and will update the issues once I know anything more. In the meantime, @todorspetkov, could you check if you can reproduce the issue in an x86-64 Android 5.0/5.1 emulator? |
@grendello I setup two Virtual Devices using Android Studio, one using Android 5.0 (Google APIs) and one using Android 5.1 (Google APIs): on both I was able to reproduce the same crash using a release build of our app. |
Update: I split our release build and produced an x86 only apk and a x86_64 only apk. On both virtual devices the x86 only apk runs fine but the x86_64 only apk crashes with above stacktrace... Just as quick fix: could I exclude x86_64 ABI from release builds and include x86 only? This should run on x86_64 CPU cell phones, right?! Or does Google Play Store require the x86_64 mandatorily? |
@todorspetkov yes, x86 should run just fine on x86_64 and in real world the latter are few and far between, so you should be fine. Regarding the fix, please see the issue I linked to - I hope to have a PR up soon which will probably fix your problem as well. |
Ok, after going through the Google Play Console docs it seems that since Agust 1 2019, x86 cannot be included alone - one must also include x86_64 when publishing apps in the store ( So we will have to wait for the bug-fix... |
Fixes: dotnet#4772 Fixes: dotnet#4852 Fixes apply to the the **Release** builds on Android 5.x devices. Android 5.x devices have a bug in their 64-bit dynamic linker which prevents it from correctly resolving shared library dependencies when a library required by the one currently being loaded is not found in the same directory. The problem is that the Android dynamic linker on those devices fails to properly interpret the internal library name (so-called `SONAME`, contained in the `DT_SONAME` field in the ELF executable header) when checking whether the library is already loaded in the process memory. Failing that check, the loader proceeds to look for the library **file** on the disk/storage medium in the predefined paths. Since `libmonosgen-2.0.so` and other libraries are not found in those paths, the search fails and the linker returns an error. Later versions of Android fix the bug in that the `DT_SONAME` field is used to properly look up already loaded shared libraries and thus the dependency resolution succeeds. The solution here is to use the Java API, `System.loadLibrary`, to preload `libmono-native.so` because the Java API is able to somehow figure out that the dependent libraries are found in the same directory and load them to satisfy the requirements. We could probably implement the same algorithms in our native code, but it feels it would be a wasted effort since Android versions above 5.x work correctly.
@todorspetkov The above PR should fix your issue as well - on devices, in Release build. The Debug build with shared runtime will not be fixed - please refer to this comment for explanation why :) |
Hi @grendello when do you expect this bugfix to make it into a xamarin-android official update? Really appreciate your help, thanks a lot. |
Fixes: dotnet#4772 Fixes: dotnet#4852 Fixes apply to the the **Release** builds on Android 5.x devices. Android 5.x devices have a bug in their 64-bit dynamic linker which prevents it from correctly resolving shared library dependencies when a library required by the one currently being loaded is not found in the same directory. The problem is that the Android dynamic linker on those devices fails to properly interpret the internal library name (so-called `SONAME`, contained in the `DT_SONAME` field in the ELF executable header) when checking whether the library is already loaded in the process memory. Failing that check, the loader proceeds to look for the library **file** on the disk/storage medium in the predefined paths. Since `libmonosgen-2.0.so` and other libraries are not found in those paths, the search fails and the linker returns an error. Later versions of Android fix the bug in that the `DT_SONAME` field is used to properly look up already loaded shared libraries and thus the dependency resolution succeeds. The solution here is to use the Java API, `System.loadLibrary`, to preload `libmono-native.so` because the Java API is able to somehow figure out that the dependent libraries are found in the same directory and load them to satisfy the requirements. We could probably implement the same algorithms in our native code, but it feels it would be a wasted effort since Android versions above 5.x work correctly.
@todorspetkov we first need to see the PR merged, I don't think we're going to see the fix in the upcoming 16.7 release, though. However, I can give you our Java startup code rebuilt with the fix so that you can replace it in your installation and rebuild your app with the fix. Please let me know if you'd like to do that, if only to test the fix. |
@grendello Yes I would like to try out the fix. I will probabely need instructions on what to do exactly :-). |
@todorspetkov no worries, it's not that hard :). Download the attachment here, unpack it in some location. Then locate your Xamarin.Android installation tree, it should be in |
@grendello Ok I performed the steps you described and produced an apk that now runs on the Emulators without problems. Now I am running a battery of tests using Firebase Robo. Just a quick question: this fix is for Android 5.x devices based both on x86 and Arm platforms, right? |
@todorspetkov great that it works for you! Yes, it's for all the supported architectures |
Fixes: #4772 Fixes: #4852 Context: https://issuetracker.google.com/issues/36950617 Fixes apply to the the **Release** builds on Android 5.x devices. A Xamarin.Android application contains multiple native libraries: $ adb shell pm list packages -f | grep -i hello package:/data/app/com.xamarin.android.helloworld-_-zYezFQQsuaiegto4HlCw==/base.apk=com.xamarin.android.helloworld $ adb shell ls /data/app/com.xamarin.android.helloworld-_-zYezFQQsuaiegto4HlCw==/lib/arm64 … libmono-native.so libmonosgen-2.0.so … Native libraries may have dependencies, e.g. `libmono-native.so` depends on `libmonosgen-2.0.so` in order to load. Once Upon A Time, Android's native linker was "not helpful" when loading native libraries through **dlopen**(3): it wouldn't use the library's directory to resolve dependencies, and thus `dlopen("libmono-native.so")` would fail. [This limitation was (mostly) fixed in Android 4.3 (API-18)][0], but a variation of this limitation is also present on some Android 5.x devices (API-21, API-22) when running *64-bit apps*. For example, if a C# API call requires loading `libmono-native.so`, then on these devices the load will fail, as `libmonosgen-2.0.so` can't be found -- which is rather unexpected, as `libmonosgen-2.0.so` is *already* loaded (!) -- which results in an app crash: UNHANDLED EXCEPTION: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeInitializationException: The type initializer for 'PanCardView.Droid.CardsViewRenderer' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.Random' threw an exception. ---> System.DllNotFoundException: libmono-native.so assembly:<unknown assembly> type:<unknown type> member:(null) at (wrapper managed-to-native) Interop+Sys.GetNonCryptographicallySecureRandomBytes(byte*,int) at Interop.GetRandomBytes (System.Byte* buffer, System.Int32 length) <0x7f86c3bbf0 + 0x0001b> in <39e41a681ea94f00bcc87fb130853dc2>:0 at System.Random.GenerateGlobalSeed () <0x7f86cb33f0 + 0x00017> in <39e41a681ea94f00bcc87fb130853dc2>:0 at System.Random..cctor () <0x7f86cb3690 + 0x0000b> in <39e41a681ea94f00bcc87fb130853dc2>:0 … The problem is that the Android dynamic linker on these devices fails to properly interpret the internal library name (so-called `SONAME`, contained in the `DT_SONAME` field in the ELF executable header) when checking whether the library is already loaded in the process memory. Failing that check, the loader proceeds to look for the library **file** on the disk/storage medium in the predefined paths. Since `libmonosgen-2.0.so` and other libraries are not found in those paths, the search fails and the linker returns an error. Later versions of Android fix the bug in that the `DT_SONAME` field is used to properly look up already loaded shared libraries and thus the dependency resolution succeeds. The solution here is to use the `System.loadLibrary()` Java API to preload `libmono-native.so`, as the Java API is able to figure out that the dependent libraries are found in the same directory and load them to satisfy the requirements. [0]: https://issuetracker.google.com/issues/36950617
Fixes: #4772 Fixes: #4852 Context: https://issuetracker.google.com/issues/36950617 Fixes apply to the the **Release** builds on Android 5.x devices. A Xamarin.Android application contains multiple native libraries: $ adb shell pm list packages -f | grep -i hello package:/data/app/com.xamarin.android.helloworld-_-zYezFQQsuaiegto4HlCw==/base.apk=com.xamarin.android.helloworld $ adb shell ls /data/app/com.xamarin.android.helloworld-_-zYezFQQsuaiegto4HlCw==/lib/arm64 … libmono-native.so libmonosgen-2.0.so … Native libraries may have dependencies, e.g. `libmono-native.so` depends on `libmonosgen-2.0.so` in order to load. Once Upon A Time, Android's native linker was "not helpful" when loading native libraries through **dlopen**(3): it wouldn't use the library's directory to resolve dependencies, and thus `dlopen("libmono-native.so")` would fail. [This limitation was (mostly) fixed in Android 4.3 (API-18)][0], but a variation of this limitation is also present on some Android 5.x devices (API-21, API-22) when running *64-bit apps*. For example, if a C# API call requires loading `libmono-native.so`, then on these devices the load will fail, as `libmonosgen-2.0.so` can't be found -- which is rather unexpected, as `libmonosgen-2.0.so` is *already* loaded (!) -- which results in an app crash: UNHANDLED EXCEPTION: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeInitializationException: The type initializer for 'PanCardView.Droid.CardsViewRenderer' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.Random' threw an exception. ---> System.DllNotFoundException: libmono-native.so assembly:<unknown assembly> type:<unknown type> member:(null) at (wrapper managed-to-native) Interop+Sys.GetNonCryptographicallySecureRandomBytes(byte*,int) at Interop.GetRandomBytes (System.Byte* buffer, System.Int32 length) <0x7f86c3bbf0 + 0x0001b> in <39e41a681ea94f00bcc87fb130853dc2>:0 at System.Random.GenerateGlobalSeed () <0x7f86cb33f0 + 0x00017> in <39e41a681ea94f00bcc87fb130853dc2>:0 at System.Random..cctor () <0x7f86cb3690 + 0x0000b> in <39e41a681ea94f00bcc87fb130853dc2>:0 … The problem is that the Android dynamic linker on these devices fails to properly interpret the internal library name (so-called `SONAME`, contained in the `DT_SONAME` field in the ELF executable header) when checking whether the library is already loaded in the process memory. Failing that check, the loader proceeds to look for the library **file** on the disk/storage medium in the predefined paths. Since `libmonosgen-2.0.so` and other libraries are not found in those paths, the search fails and the linker returns an error. Later versions of Android fix the bug in that the `DT_SONAME` field is used to properly look up already loaded shared libraries and thus the dependency resolution succeeds. The solution here is to use the `System.loadLibrary()` Java API to preload `libmono-native.so`, as the Java API is able to figure out that the dependent libraries are found in the same directory and load them to satisfy the requirements. [0]: https://issuetracker.google.com/issues/36950617
Release status update A new Preview version of Xamarin.Android has now been published that includes the fix for this item (for apps built in the Release configuration). The fix is not yet included in a Release version of Xamarin.Android. I will update this again when a Release version is available that includes the fix. Fix included in Xamarin.Android 11.0.0.3. Fix included on Windows in Visual Studio 2019 version 16.7 Preview 4. 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.7 Preview 4. To try the Preview version that includes the fix, check for the latest updates on the Preview updater channel. |
Release status update A new Release version of Xamarin.Android has now been published that includes the fix for this item (for apps built in the Release configuration). Fix included in Xamarin.Android SDK version 11.0.0.3. Fix included on Windows in Visual Studio 2019 version 16.7. To get the new version that includes the fix, check for the latest updates or install the most recent release from https://visualstudio.microsoft.com/downloads/. Fix included on macOS in Visual Studio 2019 for Mac version 8.7. To get the new version that includes the fix, check for the latest updates on the Stable updater channel. |
Description
Observing the following Exception in Firebase Crashlytics only on Android 5.0.x devices, 90% on Huawei devices. Release build (no shared mono runtime). Anyone seen somthething similar?
Basic Information
The text was updated successfully, but these errors were encountered: