NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
16.44k stars 12.93k forks source link

Darwin packages get linked with two different copies of system framework, causing strange runtime errors #12346

Open pikajude opened 8 years ago

pikajude commented 8 years ago

I spent the past eight hours figuring out why my built phantomjs2 kept segfaulting. The root cause of the segfault was the usage of NSString constants; I'm not completely sure why this happened, but I'm guessing the compiled string constant has an isa member pointing to the wrong memory location. Once I rewrite the link reference in phantomjs, from nix-built CF to system CF, everything works.

The problem can be fixed by rewriting/removing the duplicate links, but I think a more viable long-term solution is in order to avoid future confusing bugs.

copumpkin commented 8 years ago

How about putting the a DYLD_LIBRARY_PATH wrapper around the executable for now?

pikajude commented 8 years ago

I don't think that helps for absolute-path link dependencies...

copumpkin commented 8 years ago

@pikajude I think it does:

$ otool -L ./ls
./ls:
    /usr/lib/libutil.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

$ DYLD_PRINT_LIBRARIES=1 ./ls
dyld: loaded: /Users/copumpkin/Sandbox/nixpkgs/./ls
dyld: loaded: /usr/lib/libutil.dylib
dyld: loaded: /usr/lib/libncurses.5.4.dylib
dyld: loaded: /usr/lib/libSystem.B.dylib
dyld: loaded: /usr/lib/libc++.1.dylib
dyld: loaded: /usr/lib/libc++abi.dylib
dyld: loaded: /usr/lib/system/libcache.dylib
dyld: loaded: /usr/lib/system/libcommonCrypto.dylib
dyld: loaded: /usr/lib/system/libcompiler_rt.dylib
dyld: loaded: /usr/lib/system/libcopyfile.dylib
dyld: loaded: /usr/lib/system/libcorecrypto.dylib
dyld: loaded: /usr/lib/system/libdispatch.dylib
dyld: loaded: /usr/lib/system/libdyld.dylib
dyld: loaded: /usr/lib/system/libkeymgr.dylib
dyld: loaded: /usr/lib/system/liblaunch.dylib
dyld: loaded: /usr/lib/system/libmacho.dylib
dyld: loaded: /usr/lib/system/libquarantine.dylib
dyld: loaded: /usr/lib/system/libremovefile.dylib
dyld: loaded: /usr/lib/system/libsystem_asl.dylib
dyld: loaded: /usr/lib/system/libsystem_blocks.dylib
dyld: loaded: /usr/lib/system/libsystem_c.dylib
dyld: loaded: /usr/lib/system/libsystem_configuration.dylib
dyld: loaded: /usr/lib/system/libsystem_coreservices.dylib
dyld: loaded: /usr/lib/system/libsystem_coretls.dylib
dyld: loaded: /usr/lib/system/libsystem_dnssd.dylib
dyld: loaded: /usr/lib/system/libsystem_info.dylib
dyld: loaded: /usr/lib/system/libsystem_kernel.dylib
dyld: loaded: /usr/lib/system/libsystem_m.dylib
dyld: loaded: /usr/lib/system/libsystem_malloc.dylib
dyld: loaded: /usr/lib/system/libsystem_network.dylib
dyld: loaded: /usr/lib/system/libsystem_networkextension.dylib
dyld: loaded: /usr/lib/system/libsystem_notify.dylib
dyld: loaded: /usr/lib/system/libsystem_platform.dylib
dyld: loaded: /usr/lib/system/libsystem_pthread.dylib
dyld: loaded: /usr/lib/system/libsystem_sandbox.dylib
dyld: loaded: /usr/lib/system/libsystem_secinit.dylib
dyld: loaded: /usr/lib/system/libsystem_trace.dylib
dyld: loaded: /usr/lib/system/libunc.dylib
dyld: loaded: /usr/lib/system/libunwind.dylib
dyld: loaded: /usr/lib/system/libxpc.dylib
dyld: loaded: /usr/lib/libobjc.A.dylib
dyld: loaded: /usr/lib/libauto.dylib
dyld: loaded: /usr/lib/libDiagnosticMessagesClient.dylib
CONTRIBUTING.md COPYING     README.md   default.nix doc     lib     libutil.dylib   ls      maintainers nixos       pkgs        result

$ cp /usr/lib/libutil.dylib .

$ DYLD_PRINT_LIBRARIES=1 DYLD_LIBRARY_PATH=. ./ls
dyld: loaded: /Users/copumpkin/Sandbox/nixpkgs/./ls
dyld: loaded: ./libutil.dylib
dyld: loaded: /usr/lib/libncurses.5.4.dylib
dyld: loaded: /usr/lib/libSystem.B.dylib
dyld: loaded: /usr/lib/libc++.1.dylib
dyld: loaded: /usr/lib/libc++abi.dylib
dyld: loaded: /usr/lib/system/libcache.dylib
dyld: loaded: /usr/lib/system/libcommonCrypto.dylib
dyld: loaded: /usr/lib/system/libcompiler_rt.dylib
dyld: loaded: /usr/lib/system/libcopyfile.dylib
dyld: loaded: /usr/lib/system/libcorecrypto.dylib
dyld: loaded: /usr/lib/system/libdispatch.dylib
dyld: loaded: /usr/lib/system/libdyld.dylib
dyld: loaded: /usr/lib/system/libkeymgr.dylib
dyld: loaded: /usr/lib/system/liblaunch.dylib
dyld: loaded: /usr/lib/system/libmacho.dylib
dyld: loaded: /usr/lib/system/libquarantine.dylib
dyld: loaded: /usr/lib/system/libremovefile.dylib
dyld: loaded: /usr/lib/system/libsystem_asl.dylib
dyld: loaded: /usr/lib/system/libsystem_blocks.dylib
dyld: loaded: /usr/lib/system/libsystem_c.dylib
dyld: loaded: /usr/lib/system/libsystem_configuration.dylib
dyld: loaded: /usr/lib/system/libsystem_coreservices.dylib
dyld: loaded: /usr/lib/system/libsystem_coretls.dylib
dyld: loaded: /usr/lib/system/libsystem_dnssd.dylib
dyld: loaded: /usr/lib/system/libsystem_info.dylib
dyld: loaded: /usr/lib/system/libsystem_kernel.dylib
dyld: loaded: /usr/lib/system/libsystem_m.dylib
dyld: loaded: /usr/lib/system/libsystem_malloc.dylib
dyld: loaded: /usr/lib/system/libsystem_network.dylib
dyld: loaded: /usr/lib/system/libsystem_networkextension.dylib
dyld: loaded: /usr/lib/system/libsystem_notify.dylib
dyld: loaded: /usr/lib/system/libsystem_platform.dylib
dyld: loaded: /usr/lib/system/libsystem_pthread.dylib
dyld: loaded: /usr/lib/system/libsystem_sandbox.dylib
dyld: loaded: /usr/lib/system/libsystem_secinit.dylib
dyld: loaded: /usr/lib/system/libsystem_trace.dylib
dyld: loaded: /usr/lib/system/libunc.dylib
dyld: loaded: /usr/lib/system/libunwind.dylib
dyld: loaded: /usr/lib/system/libxpc.dylib
dyld: loaded: /usr/lib/libobjc.A.dylib
dyld: loaded: /usr/lib/libauto.dylib
dyld: loaded: /usr/lib/libDiagnosticMessagesClient.dylib
CONTRIBUTING.md COPYING     README.md   default.nix doc     lib     libutil.dylib   ls      maintainers nixos       pkgs        result
copumpkin commented 8 years ago

I'm wondering if we could abuse hooks and propagatedBuildInputs to make it so that any package that includes a system framework gets a magic wrapper script applied to its executables that sets DYLD_LIBRARY_PATH and/or DYLD_FRAMEWORK_PATH.

Profpatsch commented 7 years ago

(triage) what’s the status?

johbo commented 7 years ago

Think I just came across this issue, trying to use python35Packages.watchdog on darwin, which fails with a segmentation fault.

johbo commented 7 years ago

Setting DYLD_FRAMEWORK_PATH seems to work out as a quick workaround:

johannes@dev-johbo: ~/wo/watchdog (v0.8.3)
$ nix-build ~/wo/nixpkgs/default.nix -A python35Packages.watchdog
/nix/store/r7k7ycb59iykqfbjjsgqf6gcx7f6a4x1-python3.5-watchdog-0.8.3

johannes@dev-johbo: ~/wo/watchdog (v0.8.3)
$ ./result/bin/watchmedo log
Segmentation fault: 11

johannes@dev-johbo: ~/wo/watchdog (v0.8.3)
$ DYLD_FRAMEWORK_PATH=/System/Library/Frameworks ./result/bin/watchmedo log

The last command seems to work, at least it does not segfault ;)

johbo commented 7 years ago

Any ideas how one could try to approach this issue? I'd be willing to put in some work to fix this, but at the moment I am not really sure where to start with this.

I've tried to investigate a little bit and found for example that libraries like cairo or pango do load the system CF whereas atk for example seems to load the nix CF. And I found gtk2 ending up having both which seems to cause the segfaults.

copumpkin commented 7 years ago

See my suggestion in #20484 for what I think is necessary.

matthewbauer commented 7 years ago

Do @Lnl7's recent changes fix this?

johbo commented 7 years ago

Did some quick experiments on my macbook, looks promising IMO.

Details:

$ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.nixpkgsVersion'
"17.09pre105020.bbbe24f469"

$ echo $DYLD_FRAMEWORK_PATH 

$ otool -l result-dev/bin/gtk-demo | grep -i corefoundation
         name /nix/store/0hpas287vbg3rskmh5cv8kczdjhmp3am-CF-osx-10.9.5/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (offset 24)
         name /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (offset 24)

$ nix-build '<nixpkgs>' -A gtk2.dev
$ ./result-dev/bin/gtk-demo 

$ nix-build '<nixpkgs>' -A xournal
$ ./result/bin/xournal 

$ nix-build '<nixpkgs>' -A tryton
$ ./result/bin/tryton 

These applications did start without any trouble in my case. Still it looks odd when I inspect the binaries with otool, that's not important for me though.

LnL7 commented 7 years ago

It fixes the issue in most cases, but there are still packages that suffer from this. For example pythonPackages.pyqt4 this depends on both the pure CF (python) and frameworks (qt).

copumpkin commented 7 years ago

https://github.com/NixOS/nixpkgs/issues/24693

mmahut commented 4 years ago

Any news on this issue?

stale[bot] commented 4 years ago

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.