Skip to content

fix(nix): resolve ncurses cfgetospeed via dlvsym to keep portable bundle on older glibc - #2341

Draft
brainrake wants to merge 3 commits into
developfrom
fix/ncurses-old-cfgetospeed-symver
Draft

fix(nix): resolve ncurses cfgetospeed via dlvsym to keep portable bundle on older glibc#2341
brainrake wants to merge 3 commits into
developfrom
fix/ncurses-old-cfgetospeed-symver

Conversation

@brainrake

@brainrake brainrake commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • nixpkgs' bumped glibc (2.42) re-versions `cfgetospeed`, so freshly-built `ncurses` binds to the new symbol by default - breaking the portable CLI bundle on older-glibc hosts (e.g. Ubuntu 24.04, our documented supported platform), since the bundle relies on the host's own glibc.
  • `cfgetospeed` in `libncursesw.so.6` is the only affected symbol out of ~150 bundled libraries. Confirmed via ncurses' own build: same source needs only `GLIBC_2.38` on old glibc, `GLIBC_2.42` on new.
  • Fix resolves the old (functionally identical) `GLIBC_2.17`-versioned symbol at runtime via `dlvsym` (with `dlsym` fallback), instead of a link-time `.symver` directive, which conflicts with ncurses' own `--version-script` linking.
  • Verified: patched build drops the max required GLIBC version back to 2.38, matching the rest of the bundle.

Test plan

nixpkgs' bumped glibc (2.42) re-versions cfgetospeed, so a freshly built
ncurses binds to the new GLIBC_2.42 symbol by default even though nothing
about ncurses' own code changed. That breaks the portable CLI bundle on
hosts with older glibc (e.g. Ubuntu 24.04's 2.39), since the bundle
deliberately excludes glibc itself and relies on the host's.

glibc still exports the old (functionally identical) GLIBC_2.17 version
of cfgetospeed alongside the new one, so a .symver directive forces
ncurses to bind to that instead - verified the patched build against the
new glibc drops the GLIBC_2.42 requirement entirely (max symbol version
falls back to GLIBC_2.38, matching every other bundled library).
The unconditional .symver directive broke the build on older glibc
(e.g. 2.40, currently on develop): older glibc only exports one
(unversioned-from-this-perspective) definition of cfgetospeed, so
requesting the GLIBC_2.17 version explicitly fails to link
("no symbol version section for versioned symbol"). Only glibc >= 2.42
actually carries both the old and new versioned symbols, so the override
must only apply then.
…compat

The .symver approach broke the final link (ncurses' own
-Wl,--version-script conflicts with a link-time versioned external
symbol reference), and separately, the naive dlvsym-with-fallback first
attempt still linked a bare reference to cfgetospeed for its fallback
path, which just re-added the GLIBC_2.42 requirement it was meant to
avoid.

Resolving both dlvsym and its dlsym fallback dynamically (never
referencing the bare cfgetospeed identifier in compiled code) sidesteps
the linker entirely and degrades gracefully on any glibc, verified by
building the patched ncurses against the bumped glibc: no cfgetospeed
reference of any kind remains in the dynamic symbol table, and the max
GLIBC symbol requirement drops back to 2.38, matching every other
library in the bundle.
@brainrake
brainrake force-pushed the fix/ncurses-old-cfgetospeed-symver branch from 94da426 to 4350e69 Compare August 2, 2026 00:23
@blacksmith-sh

blacksmith-sh Bot commented Aug 2, 2026

Copy link
Copy Markdown

Blacksmith runners detected OOM events on the following jobs:

Job Details
postgresql-and-plugins-17.6 (aarch64-linux) View Job
Extension Dependency Analysis View Job

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.

1 participant