Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

pythemis: Extra effort to locate Themis Core library #915

Merged
merged 5 commits into from
Apr 21, 2022

Conversation

ilammy
Copy link
Collaborator

@ilammy ilammy commented Apr 17, 2022

Put in some extra effort to locate the right native library.

  • Look for libthemis.so.0 or libthemis.0.dylib first.

    Instead of looking for some Themis Core, look for the one with the proper ABI version in it. First of all, this finally allows users to install only libthemis package, without libthemis-dev. Second, this prevents PyThemis from accidentally loading Themis 1.x or 2.x libraries, should they ever be co-installed in the system.

    find_library('themis') code path remains as a fallback on Linux and macOS, and it's also used on Windows by default. No idea whether PyThemis works there, but this PR should at least not make it worse.

  • Look in some "standard" search paths as well.

    PyThemis expects Themis Core to be installed in one of the paths dynamic linker would be looking in. Normally, it all works out, but on some 🌈 special 🦄 systems Homebrew on Apple M1 installs libraries into /opt/homebrew, which – surprise! – is not in standard search paths when non-Homebrew Python is used.

    While arguably it's the user environment issue, Python developers are not very fond of debugging native library loading and that's PyThemis fault for requiring a native library in the first place, so let's at least attempt to make things "just work" before giving up.

    So on both Linux and macOS we'd be looking in /usr/local/lib where make install puts Themis Core, and on macOS we'd be looking in /opt/homebrew/lib just in case (on Intel CPUs Homebrew installs to /usr/local/lib).

Related issues:

Checklist

  • Change is covered by automated tests
  • The coding guidelines are followed
  • Public API has proper documentation
  • Changelog is updated

@ilammy ilammy added W-PyThemis 🐍 Wrapper: PyThemis, Python API O-macOS 💻 Operating system: macOS O-Linux 🐧 Operating system: Linux labels Apr 17, 2022
@ilammy ilammy added the M1 label Apr 17, 2022
Copy link
Contributor

@radetsky radetsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty well :)

ilammy added 2 commits April 18, 2022 21:10
Instead of each submodule figuring out where the native library is,
just initialize it one place and pull it from there.
@ilammy ilammy marked this pull request as ready for review April 18, 2022 12:14
@ilammy
Copy link
Collaborator Author

ilammy commented Apr 18, 2022

Rebased with no changes, swizzled out the first commit which got already merged into master. Applied suggested wording changes by @vixentael.

@ilammy ilammy added this to the 0.15.0 milestone Apr 20, 2022
ilammy added 2 commits April 21, 2022 08:56
That is, "libthemis" ABI version 0.

First of all, this makes it possible for users to avoid installing
development package of Themis on Linux. That is, only "libthemis",
without "libthemis-dev" or "libthemis-devel".

Second, it makes sure that if Themis 0.XX and Themis 2.YY are
co-installed, then this PyThemis will load Themis 0.XX library.
By default, find_library() favors the latest version, and that
could cause ABI mismatches.

On Linux, this is how 'real' binaries load libraries via run-time
dynamic linker-loader: they remember "libthemis.so.0" soname, ask
ld to load that, and if it fails then your binary fails to start.

On macOS, applications typically remember absolute path to the library,
which would be something like this for default Homebrew install:

    /usr/local/opt/libthemis/lib/libthemis.0.dylib

However, Homebrew on Apple Silicon installs libraries in /opt/homebrew
instead of /usr/local, so look there as well.

Existing behavior of using find_library('themis') is used as a fallback
on Linux and macOS. For now, this is a genuine fallback with a warning.
PyThemis 0.15 will be a test-bed for this change, and if it works fine
then some later version might load *only* versioned libraries, assuming
libthemis.so.2 would be an actual risk.

Other systems -- like Windows -- keep using find_library(). I'm not
quite sure with the story about ABI versioning on Windows specifically.
The recommended approach there is to use absolute paths, partly because
of how easy DLL hijacking is there. Anyhow, ignore this issue for now,
and just keep using whatever we were using.
Turns out, if find_library() cannot find a library it simply returns
None and then LoadLibrary() does not raise an exception for that,
instead loading a "None" library, lol. That won't do.

We had people run into situations where native library could not be
found and then the interpreter reports errors like

    AttributeError: dlsym(RTLD_DEFAULT, themis_gen_sym_key): symbol not found

which confusingly *look like* some issues with library symbols.
@ilammy
Copy link
Collaborator Author

ilammy commented Apr 21, 2022

Updated the last couple of commits to follow #917's approach.

@ilammy ilammy merged commit ec40635 into cossacklabs:master Apr 21, 2022
@ilammy ilammy deleted the python-sonames branch April 21, 2022 09:07
@vixentael
Copy link
Contributor

@ilammy we want to cherrypick this PR to release and hotfix new pythemis version.

do you see any issues with this plan?

cc @radetsky

@le-ilammy
Copy link

we want to cherrypick this PR to release and hotfix new pythemis version.

do you see any issues with this plan?

Not at all 👍

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
M1 O-Linux 🐧 Operating system: Linux O-macOS 💻 Operating system: macOS W-PyThemis 🐍 Wrapper: PyThemis, Python API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants