Skip to content

[Linux] mcpp run 无法启动:私有 glibc 2.39 与系统库 GLIBC 版本冲突,以及切换 glibc 2.44 过程中的排查与发现 #392

Description

@FarnaHerry

环境

  • OS:Linux 6.6.87.2-microsoft-standard-WSL2(WSL2,系统 Mesa)
  • mcpp 2026.8.8.2,xlings 2026.8.8.1
  • subos:default,runtime glibc@2.39
  • toolchain:llvm@22.1.8(xim-x-llvm)
  • 系统 glibc 2.43(run.sh 注释记录);系统 /lib64/libtinfo.so.6 需要 GLIBC_2.42,系统 Mesa 需要 GLIBC_2.43

现象

mcpp run 静默退出,exit 1:
sh: /home/farna/.mcpp/registry/data/xpkgs/xim-x-glibc/2.39/lib64/libc.so.6: version `GLIBC_2.42' not found (required by /lib64/libtinfo.so.6)
用 ./run.sh(显式用系统 /lib64/ld-linux-x86-64.so.2 启动)可正常运行 → 问题定位在 mcpp 私有 glibc 与系统库不兼容,而非应用代码。

根因

  1. llvm@22.1.8/bin/clang.cfg(以及 clang++.cfg / clang-22.cfg)把链接参数全部硬编码到私有 glibc 2.39:
    -B…/xim-x-glibc/2.39/lib64
    -L…/xim-x-glibc/2.39/lib64
    -Wl,--dynamic-linker=…/2.39/lib64/ld-linux-x86-64.so.2
    -Wl,-rpath,…/2.39/lib64
    -isystem …/2.39/include
  2. 因此产物 PT_INTERP 指向 2.39/ld-linux-x86-64.so.2,RUNPATH 也带 2.39 lib64。
  3. 系统库版本高于 2.39:libtinfo.so.6 要 GLIBC_2.42,系统 Mesa 要 GLIBC_2.43。
  4. 2.39 进程加载系统库 → 动态链接器报版本不够 → 进程静默退出。
  5. 这是 xim/xlings 的有意设计:glibc 包的 la 确说明 moving to 2.44 是"deliberatedecision",2.44 为 opt-in)。所以这不是简单升级能解决的默认行为。

修复:切到 glibc 2.44

2.44 > 2.43 > 2.42,私有 libc 自身满足全部系统库要求 → mcpp run 原生可启动。

改动(都在 ~/.mcpp / ~/.xlings,仓库代码零改动):

  1. ~/.xlings/subos/default/.xlings.json:"runtime": "glibc@2.39" →
    "glibc@2.44"。解析层据此更新(.xlings-resolu4,subos lib 软链 crt1.o/ld-linux/libc.so.6等全部指向 2.44)。
  2. xim-x-llvm/22.1.8/.xpkg.lua:"xim:glibc@>=2.39" → ">=2.44"(依赖约束同步)。
  3. 删除 xim-x-glibc/2.39/(决定性步骤,见机
  4. mcpp clean --bmi-cache + 全量重建:清掉焊(不清的话编译仍报 cannot open…/2.39/include/…),并让所有产物重新链接到 2.44。

机制发现(重点,建议 mcpp/xlings 侧跟进)

metic fixup 的 glibc 选择不读取 resolver 记录,而是扫描 xim-x-glibc/ 目录取"字典序第一个"版本目录,用它重新生成 clang.cfg 与 .mcpp-fixup.json。

实证链:

  • 把 runtime 改成 2.44、解析层已到 2.44 后,每次 mcpp clean 构建仍把 clang.cfg 重写成 2.39(fixup 重新生成)。
  • 手改 clang.cfg / .mcpp-fixup.json 都会被下一次 clean build 覆盖回 2.39。
  • 把 2.39 改名 2.39.off:fixup 仍选中它(2.39.off 字典序仍小于 2.44),产物路径直接变成 …/2.39.off/…。
  • 只有把 2.39 移出 xim-x-glibc/ 目录、让扫描只剩 2.44,fixup 才落到 2.44。

后果:只要 registry 里存在 2.39,无论 subos runtime 怎么配,clean build 后 toolchain 都会悄悄回到 2.39。建议 fixup 优先采用 resolver 的版本选择,或至少按语义化版本(而非字典序)排序。

切换后的状态与副作用

  • ✅ 二进制 PT_INTERP / RUNPATH 均指向 2.44;mcpp run 正常启动(tinynext 为 mcpp 直接子进程,3/3
    次测试稳定存活);aria2 引擎走 posix_spawn, 。
  • ⚠️ 新问题 A(2.44 载荷兼容性):2.44 的 libc.so.6 将 __pointer_chk_guard 作为 UND 引用、不导出 GLIBC_PRIVATE 全局符号,而系统 bash 需要它。mcpp run 会把 toolchain 库路径(含 2.44 lib64)放进 LD_LIBRARY_PATH 传给子进程 → 应用内所有 bash 调用失败(symbol lookup error: __pointer_chk_guard, version GLIBC_PRIVATE),影响 xdg-open(打开文件/文件夹/URL)、notify-send(通知)、gio trash(回收站)、深色模式 popen 探测。tinynext 自身不引用该符号,故主进程不受影响。
  • ⚠️ 新问题 B(run.sh 回归):2.44 链接的二进制在系统 ld.so (2.43) 下静默退出——2.43 供不起 2.44 引入的符号。此前唯一能跑的 run.sh 路径失效。
  • ⚠️ 脆弱点:索引中 glibc 的 latest 仍是 2.39;若某次解析/重装把 2.39 拉回 registry,fixup 扫描会让 toolchain 悄悄回退 2.39,需人工再删。

建议

  1. mcpp/xlings:fixup 的 glibc 定位改为读 re 避免字典序扫描带来的静默回退。
  2. 2.44 载荷:核查 __pointer_chk_guard 的 GLIBC_PRIVATE 导出,保证与系统 bash 等常见二进制的兼容性。
  3. 用户侧:若需要完整 bash 功能,可在应用 shell-out(system/popen)前 unsetenv("LD_LIBRARY_PATH")(应用自身的 RUNPATH 已足够)。

Activity

  1. Sunrisepeak commented on Aug 9, 2026

    @Sunrisepeak
    Member

    Draft implementation checkpoint: PR #400 now resolves one root-local RuntimeBinding, carries exact runtime payload identity, validates stored ELF closure facts, and keeps SubOS selection non-transitive. Focused RuntimeBinding/ELF tests and E2E #200/#205/#206 pass locally. This issue remains open because closure requires a reviewed merge and released-binary validation, not source-only evidence.

  2. speak-agent commented on Aug 9, 2026

    @speak-agent
    Member

    2026.8.10.1 已发布(PR #400,合入 commit 0006ce6),本 issue 报告的两条都有对应实现,
    但我不在这里关闭它——原因写在最后。

    已经落地的部分

    为什么不关

    本轮做图形栈验收时,把 <subos>/lib 放进 LD_LIBRARY_PATH 又原样复现了同一族崩溃:

    $ LD_LIBRARY_PATH=<subos>/lib timeout 600 mcpp run
    timeout: symbol lookup error: <subos>/lib/libc.so.6:
             undefined symbol: __pointer_chk_guard, version GLIBC_PRIVATE
    

    也就是说:mcpp 侧的出口已经堵上了,但「私有 glibc 与宿主 loader 相遇即死」这个物理
    事实仍然存在
    ,只要有任何一条路径把那个目录送进环境就会重现。真正的根治在 xlings 侧
    (让私有 glibc 自包含,或者让需要它的消费方走 RPATH),已作为
    openxlings/xlings#525 的证据记录。

    本 issue 的症状是环境相关的。请在 2026.8.10.1 上复核你原来的场景;确认之后再关,
    比我替你宣布修好了更可靠。

  3. Sunrisepeak commented on Aug 10, 2026

    @Sunrisepeak
    Member

    2026.8.10.2 已发布。本 issue 我仍然不在这里关闭 —— 理由在最后。

    这一版新增的、与本 issue 同一族的部分

    • mcpp pack 的自带 libc 档不再接受宿主能力。 --mode self-contained 与
      --mode static 在解析后的图里存在 run 期能力需求时,在 plan 期失败并指出
      改用 --mode vendored。两者坏在同一件事上,正是本 issue 记录的物理:
      那个 .so 带着对宿主 libc 的要求进来,而进程里没有那份。
      此前两档都链得过去、然后运行时崩或静默降级。

    • 打包产物不再残留构建机路径。 此前只重写主二进制,bundle 进来的每个 .so
      都保留着指向构建机 xlings store 的绝对 RUNPATH。

    • 加载器标签契约:可执行文件 DT_RPATH、共享库 DT_RUNPATH,链接期与 patchelf 期
      同一条契约,并在 resolution.json 留 loader_tags 记录。

    为什么还不关

    本 issue 的症状是环境相关的,而且我这台机器验不了它 ——
    它的共享 gcc 载荷 specs 已被历次安装污染(--dynamic-linker 指向一个已被改名走的
    glibc/2.44),这本身就会以本 issue 描述的方式失败,与 mcpp 的版本无关:
    已发布的 2026.8.8.2 在同一台机器上复现同样的症状。

    请在 2026.8.10.2 上复核你原来的场景。 你确认之后再关,比我替你宣布修好了可靠。

    真正的根治(让私有 glibc 自包含,或让消费方走 RPATH)仍在
    openxlings/xlings#525。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions