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

SoLoader is not compatible with Android app bundles #43

Closed
iain-merrick-fanduel opened this issue Jul 31, 2019 · 23 comments
Closed

SoLoader is not compatible with Android app bundles #43

iain-merrick-fanduel opened this issue Jul 31, 2019 · 23 comments

Comments

@iain-merrick-fanduel
Copy link

iain-merrick-fanduel commented Jul 31, 2019

We're seeing crashes in SoLoader in production when loading libreactnativejni.so. We're using React Native 0.59 and SoLoader 0.6.0.

The crash occurs on a range of devices, on Android OS versions 6 through 10. Google devices seem especially prone, notably the Pixel and Chromebook Plus V2.

The crashes appear to stem from our switch to using an app bundle rather than an APK on the Google Play store. This looks possibly related to #30, but that issue is marked as resolved in 0.6.0.

It looks like the app is sometimes attempting to link against old copies of some of the libraries. Here are some examples:

Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libreactnativejni.so caused by: dlopen failed: cannot locate symbol "_ZN3fLI7FLAGS_vE" referenced by "/data/app/com.fanduel.android.self-1/lib/arm/libglog.so"...

Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libreactnativejni.so caused by: dlopen failed: cannot locate symbol "_ZN8facebook5react15makeJIntOrThrowEx" referenced by "/data/app/com.fanduel.android.self-7bFAALdOGMNizGU2gL_5nA==/lib/arm/libreactnativejni.so"...

Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libreactnativejni.so caused by: dlopen failed: library "/data/user/0/com.fanduel.android.self/lib-0/libreactnativejni.so" not found

Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libreactnativejni.so caused by: dlopen failed: library "libfb.so" not found

Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libreactnativejni.so caused by: couldn't find DSO to load: libfb.so caused by: dlopen failed: library "/data/user/0/com.fanduel.android.self/lib-0/libfb.so" not found

Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libreactnativejni.so caused by: couldn't find DSO to load: libfb.so caused by: couldn't find DSO to load: libc++_shared.so caused by: dlopen failed: "/data/data/com.fanduel.android.self/lib-1/libc++_shared.so" is 32-bit instead of 64-bit (this last one started appearing after we added 64-bit support)

I wonder if the problem is just that the filesystem sometimes isn't fully flushed and ends up in an inconsistent state. Inspecting the SoLoader code, it tries to be robust (e.g. comparing a manifest of extracted files against the contests of the APK zipfiles) but it's hard to say if it's bulletproof. Maybe the manifest file is updated, but the writes to the .so files aren't completed, so the app thinks it has the current libraries installed when in fact it still has the old ones.

Sorry for the lack of detail, I'm still trying to get a clearer picture of what's going on!
The crash rate is quite low and we haven't managed to reproduce it ourselves. However, I think I've seen enough to be confident that it's the combination of SoLoader and app bundles that causes the problem.

We plan to switch back to using an APK instead of an app bundle to see if that avoids the problem.

@iain-merrick-fanduel
Copy link
Author

Looks potentially related: facebook/react-native#25927

@iain-merrick-fanduel
Copy link
Author

Potentially related: facebook/react-native#25536

@iain-merrick-fanduel
Copy link
Author

Confirmed that we're no longer seeing this crash after switching from app bundle back to APK on the Play Store.

@iain-merrick-fanduel
Copy link
Author

Is anyone available to take a look at this? The workaround of disabling app bundles results in a much larger APK.

@iain-merrick-fanduel iain-merrick-fanduel changed the title Occasional failure to refresh libraries when app bundle is updated SoLoader is not compatible with Android app bundles Sep 4, 2019
@iain-merrick-fanduel
Copy link
Author

Updated title to reflect that this bug definitely seems to be tied to app bundles.

@HarishJangra
Copy link

facing similar issue, apk works fine but app bundled app never crosses splash screen

@emeraldsanto
Copy link

I am also facing this issue with React Native 0.60.5, disabling Hermes seems to help too.

@exentrich
Copy link

Same issue

@ursnj
Copy link

ursnj commented Sep 26, 2019

Same issue any one having fix for this ???

@oprisnik
Copy link
Contributor

version 0.8.0 should fix this issue.

@iain-merrick-fanduel
Copy link
Author

Can we pin to the latest version of SoLoader even if we're using an older version of React Native? Or does RN need to be updated to use a new API? We're currently on RN 0.59.

@iain-merrick-fanduel
Copy link
Author

@oprisnik Also, is SoLoader 0.8.0 able to load uncompressed libraries directly from the bundle, or does it extract them to the filesystem?

@oprisnik
Copy link
Contributor

You should be able to force a given version with something like this:

facebook/react-native#25490 (comment)

The commit that adds app bundle support is c7980fc, which should actually be in 0.6.0 already - so maybe there's still an issue even with 0.8.0?

@ursnj
Copy link

ursnj commented Sep 26, 2019

i tried with react-native 0.61.1 but still issue is there. not sure what to do with this inconsistencies :(
which file we need to keep this force code ???

@IamMasterWayne

This comment has been minimized.

@iain-merrick-fanduel
Copy link
Author

The commit that adds app bundle support is c7980fc, which should actually be in 0.6.0 already - so maybe there's still an issue even with 0.8.0?

The problem we've been seeing is not that bundles are completely unsupported, but that SoLoader attempts to handle bundles and sometimes ends up with corrupted .so files.

I think something about the way .so files are extracted to the file system is just not working reliably on all devices. Unless this has been specifically investigated and addressed, I think this bug still exists.

The real test would be to re-enable app bundles and check the crash rates, but I'm not in a position to do that without being extremely confident that the bug has actually been fixed.

It would be great to see a solution that skips the extraction step completely for uncompressed native libraries (https://developer.android.com/topic/performance/reduce-apk-size#reduce-binaries). That would give us a high degree of confidence in the fix.

@benjakuben
Copy link

Bumping this issue as we are still seeing this when attempting to use app bundles for a React Native application.

Fatal Exception: java.lang.UnsatisfiedLinkError
couldn't find DSO to load: libhermes.so

RN version 0.62

@anteeek
Copy link

anteeek commented Sep 14, 2020

Same issue here, the application works on Android 8.0, but fails to start on Android 6.0:

libjscexecutor.so not found on /data/data/com.app/lib-main
SoLoader: libjscexecutor.so found on /data/app/com.app-2/lib/arm
SoLoader: libfbjni.so not found on /data/data/com.app/lib-main
SoLoader: libfbjni.so found on /data/app/com.app-2/lib/arm
SoLoader: libflipper.so not found on /data/data/com.app/lib-main
SoLoader: libflipper.so found on /data/app/com.app-2/lib/arm
[...]
ActivityManager: Displayed com.app/.MainActivity: +578ms
SoLoader: libreactnativejni.so not found on /data/data/com.app/lib-main
SoLoader: libreactnativejni.so found on /data/app/com.app-2/lib/arm
[...]
ActivityManager: App crashed! Process: com.app
ActivityManager:   Force finishing activity com.app/.MainActivity

We're using React Native, minimum SDK version is set to 18

@alexcohn
Copy link

I think something about the way .so files are extracted to the file system is just not working reliably on all devices.

This is true. See https://issuetracker.google.com/issues/147096055. People there complain not only about Xiaomi devices.

@harbolaez
Copy link

Any fix around this issue? is crazy...

@alexcohn
Copy link

@harbolaez I believe you can avoid this problem on Xiaomi and some other devices if you explicitly add android:extractNativeLibs=true for the application tag of you ApplicationManifest. Unfortunately, this makes your bundle slightly less efficient for all devices.

@ganadist
Copy link

ganadist commented Aug 15, 2021

Since Android 4.2 (JB-MR2), soloader function is not needed.
In Soloader README.md, it said

SoLoader is a native code loader for Android. 
It takes care of unpacking your native libraries and recursively loads dependencies on platforms 
that don't support that out of the box.

But in bionic document, it said
https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#changes-to-library-dependency-resolution

Until it was fixed in JB-MR2, Android didn‘t include the application library directory on the dynamic linker’s search path.
This meant that apps had to call dlopen or System.loadLibrary on all transitive dependencies 
before loading their main library. 
Worse, until it was fixed in JB-MR2, the dynamic linker's caching code cached failures too, 
so it was necessary to topologically sort your libraries and load them in reverse order.

So, here is simple solution.

  1. Use minSdkVersion 18 or higher
  2. Add following code on your application.
package com.facebook.soloader;

import android.content.Context;

public class SoLoader {
  public static final int SOLOADER_ENABLE_EXOPACKAGE = (1 << 0);
  public static final int SOLOADER_ALLOW_ASYNC_INIT = (1 << 1);
  public static final int SOLOADER_LOOK_IN_ZIP = (1 << 2);
  public static final int SOLOADER_DISABLE_BACKUP_SOSOURCE = (1 << 3);
  public static final int SOLOADER_SKIP_MERGED_JNI_ONLOAD = (1 << 4);

  public static void init(Context context,  boolean nativeExopackage) {
  }

  public static boolean loadLibrary(String libname) {
      return loadLibrary(libname, 0);
  }

  public static boolean loadLibrary(String libname, int loadFlags) throws UnsatisfiedLinkError {
      System.loadLibrary(libname);
      return true;
  }
}
  • It was okay to use yoga
  • For react native, need to check that more symbols should be exposed.
  1. Exclude soloader from build dependency

@simpleton
Copy link
Member

Version 0.10.3 has been released which supports AAB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests