Skip to content

Don't link plugins with libhts.dylib on macOS (correction to PR 1072)#1184

Merged
daviesrob merged 1 commit intosamtools:developfrom
jmarshall:macos-plugins
Dec 15, 2020
Merged

Don't link plugins with libhts.dylib on macOS (correction to PR 1072)#1184
daviesrob merged 1 commit intosamtools:developfrom
jmarshall:macos-plugins

Conversation

@jmarshall
Copy link
Copy Markdown
Member

[A followup to PR #1072, needed to fix #1176: the previous PR causes breakage limited to macOS when the main executable contains a statically linked libhts.a.]

PR #1072 changed plugin linking so that plugins are linked back to the dynamic libhts.so/.dylib, to facilitate use when libhts is itself dynamically dlopen()ed with RTLD_LOCAL, e.g., by the Python runtime which uses default dlopen() flags which on Linux means RTLD_LOCAL.

This broke plugin loading on macOS when opening plugins in an executable in which libhts.a has been statically linked, as there were then two copies of the library globals (notably hfile.c's schemes), one from the executable's libhts.a and one from the plugin's libhts.NN.dylib. (The Linux loading model does not suffer from this issue.)

The default dlopen() flag on macOS is RTLD_GLOBAL, so this can be fixed by reverting the change (on macOS only) and depending on the symbols supplied by a static libhts.a, a dynamically linked libhts.NN.dylib, or a RTLD_GLOBALly dlopen()ed libhts.NN.dylib. This rebreaks the case of dlopen()ing libhts on macOS while explicitly specifying RTLD_LOCAL, but this is not a common case.

Correspondingly adjust tests:

  • Disable the plugins-dlhts -l test case on macOS.
  • Add a test of accessing plugins from an executable with a statically linked libhts.a.

PR samtools#1072 changed plugin linking so that plugins are linked back to
the dynamic libhts.so/.dylib, to facilitate use when libhts is itself
dynamically dlopen()ed with RTLD_LOCAL, e.g., by the Python runtime
which uses default dlopen() flags which on Linux means RTLD_LOCAL.

This broke plugin loading on macOS when opening plugins in an executable
in which libhts.a has been statically linked, as there were then two
copies of the library globals (notably hfile.c::schemes), one from the
executable's libhts.a and one from the plugin's libhts.NN.dylib.
(The Linux loading model does not suffer from this issue.)

The default dlopen() flag on macOS is RTLD_GLOBAL, so this can be fixed
by reverting the change (on macOS only) and depending on the symbols
supplied by a static libhts.a, a dynamically linked libhts.NN.dylib,
or a RTLD_GLOBALly dlopen()ed libhts.NN.dylib. This rebreaks the case
of dlopen()ing libhts on macOS while explicitly specifying RTLD_LOCAL,
but this is not a common case. Fixes samtools#1176.

Disable the `plugins-dlhts -l` test case on macOS. Add a test of
accessing plugins from an executable with a statically linked libhts.a
(namely, htsfile) to test/test.pl.
@daviesrob daviesrob self-assigned this Dec 15, 2020
@daviesrob
Copy link
Copy Markdown
Member

Thanks. At some point we should look into a better method for plug-ins to get the symbols needed from the HTSlib that loaded them. Meanwhile this looks like a good improvement to the current system.

@daviesrob daviesrob merged commit 7ca2b49 into samtools:develop Dec 15, 2020
@jmarshall jmarshall deleted the macos-plugins branch December 15, 2020 19:28
jmarshall added a commit to jmarshall/pysam that referenced this pull request Dec 15, 2020
Apply PR samtools/htslib#1184. On macOS, plugins pulling in libhts.dylib
conflicts with a statically linked libhts.a from the main executable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

htslib protocol plugins (https/S3) cannot be loaded on macOS

2 participants