Fix JNI preload cache generation #10547
Merged
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.
Fixes: #10544
Context: 1a62af3
Context: cba39dc
cba39dc introduced code to preload at startup native libraries which use JNI,
to work around an issue in Android which prevents such libraries from being
properly loaded at the later time of application life.
Part of the workaround was support for updating handle of such a library in
our shared library cache. Since every library has different entries in the
cache (because we search the array using xxHash generated from various forms
of the library name), after preloading it we had to update every entry in the
DSO cache with the correct handle, so that the library is never loaded again.
The code which generates the caches and indexes at application build time worked
fine in my testing (using
dotnet build) but it turns out that usingdotnet publishinstead breaks the code in a subtle, but nasty way.
The issue is that the code which generated the index of shared libraries to preload
reused an array which stored the indexes, while generating code for different RIDs.
This resulted in the very first RID to process to contain valid indexes, the
second one would append its own indexes to the preceding RID's data, the third
RID would further append its own data etc.
This would result in the following index code generated for the subsequend RIDs:
In effect, when running on an arm64 device, we would try to load, and cache the
handle, of an entirely different shared library, leading to further problems to
find a requested symbol:
Native code attempted to load the symbol from a library that happened to be
stored at the index valid for
android-armbut not for e.g.android-arm64,which was not
libSystem.Security.Cryptography.Native.Android, leading tothe above red herring error.
Note: if all of RIDs enabled for the application are 32-bit or all
of them are 64-bit, things would work even though the generated code would
be technically incorrect. This is because all of the hashes and, thus, sort
order of the
dso_cacheentries would be the same.Fix this by making sure that the index array is not shared between different
RIDs when generating the DSO cache code.