Skip to content

Add support for pre-loading app native libraries - #713

Closed
mauiaaron wants to merge 1 commit into
dotnet:masterfrom
mauiaaron:feature-preload-app-native-libs
Closed

Add support for pre-loading app native libraries#713
mauiaaron wants to merge 1 commit into
dotnet:masterfrom
mauiaaron:feature-preload-app-native-libs

Conversation

@mauiaaron

Copy link
Copy Markdown
  • Libraries are listed one-per-line in 'ld_preload.txt' file bundled in Android assets

  • Pre-loading of the libraries occurs before libmonodroid.so is loaded

  • The primary use case here is to load a native crash manager (e.g., a custom-built libBreakpad.so) which can install its signal handlers (via ELF SHT_INIT_ARRAY ctors) below the Mono signal handlers

    * Libraries are listed one-per-line in 'ld_preload.txt' file bundled in
      Android assets

    * Pre-loading of the libraries occurs before libmonodroid.so is loaded

    * The primary use case here is to load a native crash manager (e.g., a
      custom-built libBreakpad.so) which can install its signal handlers (via
      ELF SHT_INIT_ARRAY ctors) below the Mono signal handlers
@monojenkins

Copy link
Copy Markdown

Hello! I'm the build bot for the Mono project.

I need approval from a Mono team member to build this pull request. A team member should reply with "approve" to approve a build of this pull request, "whitelist" to whitelist this and all future pull requests from this contributor, or "build" to explicitly request a build, even if one has already been done. Additional trigger words are available here.

Contributors can ignore this message.

@dnfclas

dnfclas commented Aug 2, 2017

Copy link
Copy Markdown

@mauiaaron,
Thanks for your contribution.
To ensure that the project team has proper rights to use your work, please complete the Contribution License Agreement at https://cla2.dotnetfoundation.org.

It will cover your contributions to all .NET Foundation-managed open source projects.
Thanks,
.NET Foundation Pull Request Bot

@dnfclas

dnfclas commented Aug 2, 2017

Copy link
Copy Markdown

@mauiaaron, thanks for signing the contribution license agreement. We will now validate the agreement and then the pull request.

Thanks, .NET Foundation Pull Request Bot

@jonpryor

jonpryor commented Aug 2, 2017

Copy link
Copy Markdown
Contributor

I don't like this PR. Which isn't to say that it can't be salvaged; I'm just uncertain about the intended use case.

  • Libraries are listed one-per-line in 'ld_preload.txt' file bundled in Android assets

This is not discoverable. Certainly, documentation can be written and read, but historically developers don't read (much) documentation. I thus fear it won't be used.

Assuming it should be used.

  • Pre-loading of the libraries occurs before libmonodroid.so is loaded

This implicitly assumes that the only way to preload libraries is through this mechanism, which isn't the case. There are two other ways to preload libraries:

  1. By doing what Xamarin.Android does, and "abusing" the //provider/@android:initOrder attribute.

    One problem with this at present is that Xamarin.Android hardcodes our mono.MonoRuntimeProvider to have an initOrder value of int.MaxValue, but this is something we certainly should change so that other providers can be higher. (We actually want to change this; such a change is part of PR [Xamarin.Android.Build.Tasks] Add support for new InstantRun #609, still in-progress, and it lowers our initOrder value to 2 billion.)

    In this scenario, you would "preload" libraries by providing a new Java ContentProvider subclass and corresponding AndroidManifest.xml entry to force loading before mono.MonoRuntimeProvider is run.

  2. Mono has an API to uninstall and install signal handlers:

     Mono.Runtime.RemoveSignalHandlers ();
     InstallThirdPartySignalHandlers ();
     Mono.Runtime.InstallSignalHandlers ();
    

    Here, InstallThirdPartySignalHandlers() could be any code which causes your 3rd party libraries to be loaded and run their initialization code.

Finally, this PR requires that the native library export a JNI_OnLoad() function to deal with initialization. (System.loadLibrary() only loads the library and invokes JNI_OnLoad(); nothing else is invoked, except for "constructor functions" within the .so...which I'll henceforth ignore.)

This is not necessarily the case for all libraries which would need to be involved in preloading.

  • The primary use case here is to load a native crash manager (e.g., a custom-built libBreakpad.so) which can install its signal handlers (via ELF SHT_INIT_ARRAY ctors) below the Mono signal handlers

Assuming your libBreakpad.so is anything like this one, there is no JNI_OnLoad() export. This means you'd be relying on "ELF SHT_INIT_ARRAY ctors," which I personally wouldn't like (it means I need to think about "global state" more to ensure that things happen in the order I think they are.)

Additionally, this is (more or less) exactly the scenario that Mono.Runtime.RemoveSignalHandlers() is intended for:

// No idea what this declaration *should* be...
[DllImport ("Breakpad")]
static extern void Java_net_hockeyapp_android_NativeCrashManager_nativeSetUpBreakpad(IntPtr jnienv, IntPtr klass);

public static void InitBreakpad()
{
    Mono.Runtime.RemoveSignalHandlers ();
    Java_net_hockeyapp_android_NativeCrashManager_nativeSetUpBreakpad (JNIEnv.Handle, IntPtr.Zero);
    Mono.Runtime.InstallSignalHandlers ();
}

(Here I'm assuming that Java_net_hockeyapp_android_NativeCrashManager_nativeSetUpBreakpad() is the appropriate initialization function, but that could very well be wrong.)

@mauiaaron

Copy link
Copy Markdown
Author

Hi @jonpryor, thank you for your careful review. Yes currently we are relying on ELF SHT_INIT_ARRAY ctors to perform initialization before Mono.

Apologies, I was not aware of the Mono.Runtime.{Remove,Install}SignalHandlers() API, which is a much cleaner way to do this.

"Certainly, documentation can be written and read, but historically developers don't read (much) documentation" ... Yes, I think I make this point perfectly with this PR ;)

I will investigate the Mono signal handler API and report back.

@mauiaaron

Copy link
Copy Markdown
Author

Suggested API works fine in debug and release modes, so withdrawing this PR. Thanks!

@mauiaaron mauiaaron closed this Aug 2, 2017
@jonpryor

jonpryor commented Aug 2, 2017

Copy link
Copy Markdown
Contributor

Speaking of actual documentation on Mono.Runtime.RemoveSignaHandlers()...

http://www.mono-project.com/docs/advanced/signals/

@github-actions github-actions Bot locked and limited conversation to collaborators Feb 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants