Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python: remove LD_LIBRARY_PATH hack from running python environment #1562

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

vlaci
Copy link
Contributor

@vlaci vlaci commented Oct 30, 2024

Injecting LD_LIBRARY_PATH to the Python runtime environment is great
to bypass the need of having to patch non-nix binaries loaded into
that environment, however it breaks down, when Python executes any
other program not compiled for the given Nix system, e.g. a shell
script via subprocess.

To work this around, devenv will inject a pth1 file to the virtual
environment it creates, which mangles the LD_LIBRARY_PATH variable,
undoing any changes to it made by devenv but preserving changes from
other sources.

I am unsure what the best way would be to integrate this, bit I think the approach in general is sane. I am tested only the poetry case currently.

Fixes #1111

Footnotes

  1. https://docs.python.org/3/library/site.html

vlaci added a commit to onekey-sec/unblob that referenced this pull request Oct 30, 2024
Flake lock file updates:

• Updated input 'devenv':
    'github:vlaci/devenv/5186fecbe2835ac45018ea4940388f8523bf1624' (2024-10-04)
  → 'github:vlaci/devenv/953a526754c5ff5e64ab6925c4388b26ae2c45c6' (2024-10-30)

From the related PR[^1] in `devenv`:

Injecting `LD_LIBRARY_PATH` to the Python runtime environment is great
to bypass the need of having to patch non-nix binaries loaded into
that environment, however it breaks down, when Python executes any
other program not compiled for the given Nix system, e.g. a shell
script via `subprocess`.

To work this around, `devenv` will inject a `pth`[^2] file to the virtual
environment it creates, which mangles the `LD_LIBRARY_PATH` variable,
undoing any changes to it made by `devenv` but preserving changes from
other sources.

[^1]: cachix/devenv#1562
[^2]: https://docs.python.org/3/library/site.html
vlaci added a commit to onekey-sec/unblob that referenced this pull request Oct 30, 2024
Flake lock file updates:

• Updated input 'devenv':
    'github:vlaci/devenv/5186fecbe2835ac45018ea4940388f8523bf1624' (2024-10-04)
  → 'github:vlaci/devenv/385d38cfb6872e7f95cae30d94f7fc4afd23fd76' (2024-10-30)

From the related PR[^1] in `devenv`:

Injecting `LD_LIBRARY_PATH` to the Python runtime environment is great
to bypass the need of having to patch non-nix binaries loaded into
that environment, however it breaks down, when Python executes any
other program not compiled for the given Nix system, e.g. a shell
script via `subprocess`.

To work this around, `devenv` will inject a `pth`[^2] file to the virtual
environment it creates, which mangles the `LD_LIBRARY_PATH` variable,
undoing any changes to it made by `devenv` but preserving changes from
other sources.

[^1]: cachix/devenv#1562
[^2]: https://docs.python.org/3/library/site.html
Copy link
Contributor

@bobvanderlinden bobvanderlinden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR! The idea of using a pth file makes a lot of sense 👍

pth_file =
let
exec_content = ''
ld_library_path_var = "DYLD_LIBRARY_PATH" if sys.platform == "darwin" else "LD_LIBRARY_PATH"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fairly sure DYLD_LIBRARY_PATH doesn't propagate to subprocesses. So it is probably not needed to support it here.

Maybe the pth file only needs to be added on Linux machines?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea about it. I am okay to remove it

os.environ[ld_library_path_var] = ld_library_path.removeprefix(ld_library_path_prefix + ":")
'';
in
pkgs.writeText "devenv.pth" ''import os; exec("""${builtins.replaceStrings [ "\n" ] [ "\\n" ] exec_content}""")'';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need exec? I thought it might be possible to be executed in pth as-is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pth is executed line by line, so this is the only way to use multi-line constructs like if conditions

@bobvanderlinden
Copy link
Contributor

I was thinking, since this will probably be needed just for Linux, that it might be nice to eventually have an LD_PRELOAD that removed the path from LD_LIBRARY_PATH. That way this exact same trick can be applied to ruby, nodejs and more.

Still useful to have this pth to see how it fares in the python world.

Injecting `LD_LIBRARY_PATH` to the Python runtime environment is great
to bypass the need of having to patch non-nix binaries loaded into
that environment, however it breaks down, when Python executes any
other program not compiled for the given Nix system, e.g. a shell
script via `subprocess`.

To work this around, `devenv` will inject a `pth`[^1] file to the virtual
environment it creates, which mangles the `LD_LIBRARY_PATH` variable,
undoing any changes to it made by `devenv` but preserving changes from
other sources.

Fixes cachix#1111

[^1]: https://docs.python.org/3/library/site.html
@domenkozar
Copy link
Member

Can we get some tests for this?

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.

Mixing system packages with python results in shared library errors
3 participants