Description
Patch the Python interpreter to use the user stdenv’s glibc instead of a hardcoded one. Rebuild the patched package whenever the stdenv changes.
This would be a comprehensive, but also very involved fix. Many of the errors we see seem to be caused by old packages (especially python and ruby) depending on an old glibc. This causes issues because a process can only load glibc once, and the first thing to need it determines the version.
For example, Python 3.5 is no longer maintained in nixpkgs. The last version of glibc that it was built with was 2.34. This means that before the interpreter even runs any Python code, glibc 2.34 has already been loaded into the process by the linker. If at any point there’s Python code that attempts to use a newer version of glibc, it will always crash.
This is easy to run into when using pip to install Python packages that have native code extensions. Either pip downloads a cached binary that needs a newer glibc (some packages no longer offer prebuilt binaries for this reason), or it compiles one itself by calling gcc
. The gcc compiler comes from the Nix stdenv, which is usually added by the Nix installer and is therefore almost always newer than a Python from 2015.
The diagram below attempts to illustrate the problem:
graph TD
python[Python 3.5] -->|depends on| glibc234[glibc 2.34]
python -->|runs| app[MyApp]
app -->|imports| psycopg2 -->|loads| psycopg.so
pip[pip install psycopg2] -->|calls| gcc["gcc (stdenv)"] -->|builds| psycopg.so -->|depends on| glibc2.38["glibc 2.38 (stdenv)"]
The same thing happens with Ruby (see #1772).
Also note that although this bug most commonly occurs with Python and Ruby, it can occur with any program that attempts to load shared libraries not known by Nix at build-time. For example, a program that supports plugins or one that happens to call dlopen
at runtime.
Patching a package (most likely python or ruby) to use the stdenv glibc ensures that any compiled C extensions will be linked against the same glibc as the interpreter. This is in contrast to what we do today where will patch an arbitrarily chosen and hard-coded glibc version.