Skip to content

pythemis: Extra effort to locate Themis Core library - #915

Merged
ilammy merged 5 commits into
cossacklabs:masterfrom
ilammy:python-sonames
Apr 21, 2022
Merged

ilammy merged 5 commits into
cossacklabs:masterfrom
ilammy:python-sonames

Conversation

@ilammy

@ilammy ilammy commented Apr 17, 2022 •

Copy link
Copy Markdown
Collaborator

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 🌈 ï―“ï―ï―…ï―ƒï―‰ï―ï―Œ ðŸĶ„ 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

@radetsky radetsky left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks pretty well :)

Comment thread src/wrappers/themis/python/pythemis/__init__.py Outdated
Comment thread src/wrappers/themis/python/pythemis/__init__.py Outdated
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

ilammy commented Apr 18, 2022

Copy link
Copy Markdown
Collaborator Author

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

Comment thread src/wrappers/themis/python/pythemis/__init__.py Outdated
@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

ilammy commented Apr 21, 2022

Copy link
Copy Markdown
Collaborator Author

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
Copy Markdown
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
Copy Markdown

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

do you see any issues with this plan?

Not at all 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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