Skip to content

Conversation

@grendello
Copy link
Contributor

@grendello grendello commented Aug 25, 2025

Context: cba39dc
Context: #10376
Context: #10324

cba39dc implemented preloading of JNI-using native libraries but it missed to update
alias entries for each preloaded library.

During application build we generate native code that contains cache for each native
library packaged with the managed application code. Each library follows the same
naming pattern: lib<NAME>.so. However, the managed code can refer to those libraries
(when e.g. declaring a p/invoke with the [DllImporrt] attribute) using different forms
of names. The request may have a form of lib<NAME> or <NAME> etc.

When the runtime tries to resolve the p/invoke symbol, it first needs to load the shared
library. This is done (in our case) by using a callback into our runtime which then tries
to find the library and load it. Should the attempt fail, the runtime will mutate the
library name and ask as again until all the possible names are tried or the library is
loaded successfully. This roundtrip is pretty expensive, so in our native library loader
code we implemented (in c227042) a scheme where at build time we mutate library names
ourselves and a separate entry for each name mutation in the shared library cache. This
way, when the runtime request comes, we perform a single search and are able to find
the library no matter what name the managed code requested.

Each of the cache entries contains, among other things irrelevant to this PR, a field
which stores the native library's handle, after it is loaded. cba39dc loaded the
library and set that field in just a single cache entry, the one corresponding to the
canonical library name (lib<NAME>.so) but it failed to set the field in all the aliases.
This resulted in an attempt to load the library again, with the managed code requesting it
by a different name, finding the corresponding cache entry and seeing that its handle is
unset. However, since the request was sent from a different thread, we attempted to load
the library on the main thread (described in detail in cba39dc commit message), which
attempt always failed leading to an endless loop and application crash/hang while debugging.

Fix the issue by setting native shared library handle in all the cache entries corresponding
to various mutations of the library name. This makes sure that further requests to load the
library will see the handle set in cache and use it, instead of attempting to load the it
again.

grendello and others added 2 commits August 26, 2025 10:27
Context: ee43633

Hitting F5 in Visual Studio for a `dotnet new maui` app produces a loop such as:

    08-25 09:40:36.759 32259 32293 D monodroid-assembly: monodroid_dlopen: hash match found, DSO name is 'libSystem.Security.Cryptography.Native.Android.so'
    08-25 09:40:36.759 32259 32293 D monodroid-assembly: Trying to load loading shared JNI library /data/user/0/com.companyname.testgrendel/files/.__override__/arm64-v8a/libSystem.Security.Cryptography.Native.Android.so with System.loadLibrary
    08-25 09:40:36.759 32259 32293 D monodroid-assembly: Running DSO loader on thread 32293, dispatching to main thread

This does not happen for:

* `dotnet new android` project
* At the command-line
* Using Ctrl+F5 in Visual Studio

I was able to also reproduce this issue in a `static MainActivity`
constructor that uses `HttpClient`, adding a test doing the same
thing.
@grendello grendello force-pushed the dev/grendel/dso-preload-cache-fix branch from 51af2cc to e522144 Compare August 26, 2025 08:28
@grendello
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@grendello grendello changed the title [WIP] When preloading shared JNI libraries, update alias entries too [native] When preloading shared JNI libraries, update alias entries too Aug 27, 2025
@grendello grendello marked this pull request as ready for review August 27, 2025 08:02
@grendello grendello merged commit 1a62af3 into main Aug 28, 2025
59 checks passed
@grendello grendello deleted the dev/grendel/dso-preload-cache-fix branch August 28, 2025 07:54
@github-actions github-actions bot locked and limited conversation to collaborators Sep 27, 2025
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.

3 participants