Skip to content

libcxx-{15,16,etc} segfault when multiple libcxx loaded #269548

@ghost

Description

Describe the bug

libcxx is a c++ standard library used on x64 darwin and when it is loaded by dlopen or as a result of a dlopen eg: import requests on python the program segfaults in the initialization of libcxx.

Termination Signal:    Segmentation fault: 11
[...]
Application Specific Information:
/nix/store/x4s0wi6d2z38wa0jb4yf769sl1c0c50z-libcxx-16.0.6/lib/libc++.1.0.dylib

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   ???                                 000000000000000000 0 + 0
1   libc++.1.0.dylib                    0x00000001027aeab8 std::__1::__stdinbuf<char>::imbue(std::__1::locale const&) + 40
2   libc++.1.0.dylib                    0x00000001027ae2af std::__1::DoIOSInit::DoIOSInit() + 143
3   libc++.1.0.dylib                    0x00000001027af8bd _GLOBAL__I_000100 + 45
4   dyld                                0x000000010589db47 ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 535
5   dyld                                0x000000010589df52 ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 40
6   dyld                                0x0000000105898ae6 ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 492
7   dyld                                0x0000000105898a51 ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 343
8   dyld                                0x000000010589689f ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 191
9   dyld                                0x0000000105896940 ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 82
10  dyld                                0x0000000105886a12 dyld::runInitializers(ImageLoader*) + 82
11  dyld                                0x000000010589211a dlopen_internal + 616
12  libdyld.dylib                       0x00007fff20550c94 dlopen_internal(char const*, int, void*) + 185
13  libdyld.dylib                       0x00007fff2053f07e dlopen + 28
14  libpython3.11.dylib                 0x0000000101aba0c7 _PyImport_FindSharedFuncptr + 199
[...]
Trap Number:     14

older versions of libcxx [6-14] dlopen fine. when libcxx is linked into main executable dlopen is also fine.

the macOS system was created by the steps outlined https://github.com/kholia/OSX-KVM selecting the big sur install media and run under qemu on linux.

note that a vm setup using the monterey install media does not have this issue.

Steps To Reproduce

just need to dlopen the lib. see below for a nix-shell script which builds for libcxx[6, 16].

#include <dlfcn.h>
#include <stdio.h>

int
main(int argc, const char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "usage: %s dynamic-library\n", argv[0]);
        return 1;
    }
    const char *lib = argv[1];
    int failed = dlopen(lib, RTLD_LOCAL | RTLD_LAZY) == 0;
    printf("dlopen %s: %s\n", lib, failed ? "failed" : "succeeded");
    return failed;
}
> nix-shell dlopen-tests.nix --run runtests
***** testing dlopen of libcxx ****
dlopen /nix/store/yjkk8zwfn0q6wdmz8sasj3bhcdlkf90m-libcxx-6.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/18hkjaj5v91zds2mchmggxa2fp9f5cn1-libcxx-7.1.0/lib/libc++.dylib: succeeded
dlopen /nix/store/yws4wg89q701pvvykph7ccbck37v6fvc-libcxx-8.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/y3xmblmfqpmi0qdyfqyhr5vn81s758wr-libcxx-9.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/rajjsgxwkbxv119v7dj4ai611d0vsgay-libcxx-10.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/5pzxpa71pnqnfzkdzjbm9k23ni2p7dvj-libcxx-11.1.0/lib/libc++.dylib: succeeded
dlopen /nix/store/dc16w8y92incrnsbnywsib62hwrdns5n-libcxx-12.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/bw2b7sirq8239xss5psg1211vpzarvgv-libcxx-13.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/mm41lcrgrhxd3bbzpckjnn5krxnifv5r-libcxx-14.0.6/lib/libc++.dylib: succeeded
/nix/store/6z0angjrkksixrvs5c0g080fh8813p06-runtests/bin/runtests: line 3:   614 Segmentation fault: 11  dltest_$x
dltest_15 failed with 139
/nix/store/6z0angjrkksixrvs5c0g080fh8813p06-runtests/bin/runtests: line 3:   615 Segmentation fault: 11  dltest_$x
dltest_16 failed with 139
***** testing dlopen of libcxx when linked to executable *****
dlopen /nix/store/yjkk8zwfn0q6wdmz8sasj3bhcdlkf90m-libcxx-6.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/18hkjaj5v91zds2mchmggxa2fp9f5cn1-libcxx-7.1.0/lib/libc++.dylib: succeeded
dlopen /nix/store/yws4wg89q701pvvykph7ccbck37v6fvc-libcxx-8.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/y3xmblmfqpmi0qdyfqyhr5vn81s758wr-libcxx-9.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/rajjsgxwkbxv119v7dj4ai611d0vsgay-libcxx-10.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/5pzxpa71pnqnfzkdzjbm9k23ni2p7dvj-libcxx-11.1.0/lib/libc++.dylib: succeeded
dlopen /nix/store/dc16w8y92incrnsbnywsib62hwrdns5n-libcxx-12.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/bw2b7sirq8239xss5psg1211vpzarvgv-libcxx-13.0.1/lib/libc++.dylib: succeeded
dlopen /nix/store/mm41lcrgrhxd3bbzpckjnn5krxnifv5r-libcxx-14.0.6/lib/libc++.dylib: succeeded
dlopen /nix/store/z03ngg5lzjapddhnpc1yi8mbry74n3ai-libcxx-15.0.7/lib/libc++.dylib: succeeded
dlopen /nix/store/j2m79j8hxp824md7ls0gni20al57k7y4-libcxx-16.0.6/lib/libc++.dylib: succeeded
# dlopen-tests.nix
{pkgs ? import <nixpkgs> {}}:
let
  dltest = pkgs.callPackage (
    { lib
    , stdenv
    , libcxx
    , name ? "dltest"
    , runCommandCC
    , writeText
    }:
    let
      ext = stdenv.hostPlatform.extensions.sharedLibrary;
      libpath = "${lib.getLib libcxx}/lib/libc++${ext}" + lib.optionalString stdenv.isLinux ".1";
      code = writeText "${name}.c" ''
        #include <dlfcn.h>
        #include <stdio.h>

        int
        main(void)
        {
            int failed = dlopen("${libpath}", RTLD_LOCAL | RTLD_LAZY) == 0;
            printf("dlopen %s: %s\n", "${libpath}", failed ? "failed" : "succeeded");
            return failed;
        }
      '';
    in
      runCommandCC name {src = code;} ''
        [[ -f "${libpath}" ]] || exit 1
        mkdir -p "$out"/bin
        cc -Wall -Werror -O2 -o "$out/bin/${name}" "$src" -ldl
        cc -Wall -Werror -O2 -o "$out/bin/linked_${name}" "$src" -ldl "${libpath}"
      ''
  );

  shell =
  let
    inherit (pkgs) lib mkShell writeShellScriptBin;
    getTest = ver:
      dltest {
        name = "dltest_${ver}";
        libcxx = pkgs.${"llvmPackages_${ver}"}.libcxx;
      };
    # edit: llvm7 was removed
    versions = [ 6 ] ++ lib.range 8 16;
  in
    mkShell {
      packages =
        map getTest (map toString versions)
        ++ [
          (writeShellScriptBin "runtests" ''
            echo "***** testing dlopen of libcxx ****" >&2
            for x in ${toString versions}
            do
              dltest_$x || echo dltest_$x failed with $? >&2
            done
            echo "***** testing dlopen of libcxx when linked to executable *****" >&2
            for x in ${toString versions}
            do
              linked_dltest_$x || echo linked_dltest_$x failed with $? >&2
            done
          '')
        ];
      shellHook = "runtests";
    };
in
  shell

Expected behavior

libcxx loads into the address space of the program and the initialization routines succeed.

Additional context

dltest_15_2023-11-23-183122_odel.crash.txt
dltest_16_2023-11-23-183122_odel.crash.txt
python3.11_2023-11-22-002452_odel.crash.txt

Notify maintainers

@dtzWill @Ericson2314 @lovek323 @primeos @alyssais @RaitoBezarius @rrbutani @sternenseemann

Metadata

 - system: `"x86_64-darwin"`
 - host os: `Darwin 20.6.0, macOS 10.16`
 - multi-user?: `yes`
 - sandbox: `no`
 - version: `nix-env (Nix) 2.19.1`
 - channels(root): `"nixpkgs"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixpkgs`
>  sw_vers
ProductName:    macOS
ProductVersion: 11.7.10
BuildVersion:   20G1427
> uname -a
Darwin odel.lan 20.6.0 Darwin Kernel Version 20.6.0: Thu Jul  6 22:12:47 PDT 2023; root:xnu-7195.141.49.702.12~1/RELEASE_X86_64 x86_64 i386 Darwin

Priorities

Add a 👍 reaction to issues you find important.

Metadata

Metadata

Assignees

No one assigned

    Labels

    0.kind: bugSomething is broken6.topic: llvm/clangIssues related to llvmPackages, clangStdenv and related
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions