Use different soname for Dart SDK Android build - #204
Conversation
rkistner
left a comment
There was a problem hiding this comment.
I'm happy with the change.
To help with my understanding, can the same thing happen by including multiple copies of the same .so file produced here? For example by using the both the Dart and the Dotnet SDKs in the same app?
I believe the same thing would happen if both the Dart and Dotnet SDKs were used in the same app, yes. I am not familiar with C# SQLite bindings though. If they work by bundling a |
On Android, the core extension is distributed in two ways:
.sofiles attached to GitHub releases (used by the Dart and Dotnet SDKs).Through peculiar but not entirely unreasonable setups, it's possible to end up with both in the same app. powersync-ja/powersync.dart#442 is an example of this: One database is managed by the PowerSync Dart SDK, another one by the Kotlin SDK. In this setup, two copies of SQLite and the core extension are included in the app. As long as they never touch the same database file, this should be fine. However, because the two builds have the same
sonameentry, the Android loader considers them equal and won't load them both. This causessqlite3_powersync_initto be called twice with differentsqlite3_api_routinespointers, which quickly leads to crashes as we try to use database pointers from one SQLite copy with function pointers from the other.To fix this, this gives the distributions unique names: Files in the Android library keep their
libpowersync.soname, while standalone files are namedlibpowersync_core.so, the name used by the Dart build hook.I have verified the following with assets attached to CI runs:
patchelf --print-sonameonlibpowersync.$arch.android.sofiles printslibpowersync_core.so.patchelf --print-sonameon JNI files in theaarprintslibpowersync.so, same as before.