From: Wolfgang Walther <walther@technowledgy.de>
To: PostgreSQL Bugs <pgsql-bugs@lists.postgresql.org>
Subject: Regression tests fail with musl libc because libpq.so can't be loaded
Date: Sat, 16 Mar 2024 13:38:48 +0100
Message-ID: <fddd1cd6-dc16-40a2-9eb5-d7fef2101488@technowledgy.de> (raw)
Running the regression tests when building with musl libc fails, with
errors like the following:
ERROR: could not load library
"<builddir>/tmp_install/usr/lib/postgresql/libpqwalreceiver.so": Error
loading shared library libpq.so.5: No such file or directory (needed by
<builddir>/tmp_install/usr/lib/postgresql/libpqwalreceiver.so)
This was observed in Alpine Linux [1] and nixpkgs [2] a few years ago. I
now looked at this a bit and this is what happens:
- The temporary install location is set via LD_LIBRARY_PATH in the
regression tests, so that postgres can find those libs.
- All tests which load an extension / shared module via dlopen() fail,
when the loaded library in turn depends on another library in
tmp_install - I think in practice it's libpq.so all the time.
- LD_LIBRARY_PATH is used correctly to look for the direct dependency
loaded in dlopen(...), but is not taken into account anymore when trying
to locate libpq.so. This step only fails with musl, but works fine with
glibc.
I can reproduce this with a simple Dockerfile (attached), which uses the
library/postgres-alpine image, moves libpq.so to a different folder and
points LD_LIBRARY_PATH at it. Build and run the dockerfile like this:
docker build . -t pg-musl && docker run --rm pg-musl
This Dockerfile can easily be adjusted to work with the debian image -
which shows that doing the same with glibc works just fine.
Even though this originated in "just" the regression tests, I'm filing
this as a bug, because:
- The docs explicitly mention LD_LIBRARY_PATH support to point at a
different /lib folder in [3].
- This can clearly break outside the test-suite as shown with the
Dockerfile.
I tried a few more things:
- When I add an /etc/ld-musl-$(ARCH).path file and add the path to
libpq.so's libdir to it, libpq.so can be found.
- When I add the path to libpq.so as an rpath to the postgres binary,
libpq.so can be found.
Both is not surprising, but just confirms musl-ld actually works as
expected. It's just LD_LIBRARY_PATH that seems to not be passed on.
To rule out a musl bug, I also put together a very simple test-case of
an executable loading liba with dlopen(), which depends on libb and then
constructing the same scenario with LD_LIBRARY_PATH. This works fine
when compiled with glibc and musl, too. Thus, I believe the problem to
be somewhere in how postgres loads those libraries.
Best,
Wolfgang
[1]:
https://github.com/alpinelinux/aports/commit/d67ceb66a1ca9e1899071c9ef09fffba29fa0417#diff-2bd25b517...
[2]:
https://github.com/NixOS/nixpkgs/commit/09ffd722072291f00f2a54d7404eb568a15e562a
[3]: https://www.postgresql.org/docs/current/install-post.htmlAttachments:Dockerfile (text/plain, 369B) download
FROM postgres:16-alpine
ENV POSTGRES_HOST_AUTH_METHOD=trust
ENV LD_LIBRARY_PATH=/opt/lib
RUN mkdir -p /opt/lib && mv /usr/local/lib/libpq.so* /opt/lib
# This causes dlopen(libpqwalreceiver.so)
COPY <<-EOF /docker-entrypoint-initdb.d/create-subscription.sql
CREATE SUBSCRIPTION sub1
CONNECTION 'dbname=doesnotexist' PUBLICATION pub1
WITH (connect = false);
EOF
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-bugs@postgresql.org
Cc: walther@technowledgy.de, pgsql-bugs@lists.postgresql.org
Subject: Re: Regression tests fail with musl libc because libpq.so can't be loaded
In-Reply-To: <fddd1cd6-dc16-40a2-9eb5-d7fef2101488@technowledgy.de>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox