[native] When preloading shared JNI libraries, update alias entries too #10444
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 formsof 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.