Skip to content

Conversation

@topolarity
Copy link
Member

Somewhat of a companion to #60248.

For a small application that has just started up fork() is not a huge concern, but it's quite heavy-handed for Julia- as-a-library scenarios where resident memory may already be large. Many soft-embedded targets also do not support fork() well, so it is good for our compatibility to adjust this.

Rather than relying on the linker to do all of the heavy lifting, this changes our libstdcxx probe sequence to directly parse the ld.so.cache and libstdc++.so.6 files. As long as we can expect /etc/ld.so.cache to be the same path on all Linux systems, this seems to be a reliable way to locate system libraries.

@topolarity topolarity added the system:linux Affects only Linux label Nov 26, 2025
@topolarity topolarity marked this pull request as draft November 26, 2025 17:26
@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch 3 times, most recently from 79f02b0 to b668d14 Compare November 26, 2025 17:42
@topolarity topolarity marked this pull request as ready for review November 26, 2025 17:46
@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch 2 times, most recently from 535e217 to 6916b81 Compare November 27, 2025 01:17
@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch 2 times, most recently from 50164ec to 39f68a7 Compare December 1, 2025 15:17
@topolarity
Copy link
Member Author

topolarity commented Dec 1, 2025

@gbaraldi pointed out that /etc/ld.so.cache is not available (quite intentionally) on Nix.

Nonetheless our libstdc++ probing is already not very functional on NixOS:

$ nix-shell -p julia_111-bin
$ strace julia -e '' 2>&1 | grep libstdc++
openat(AT_FDCWD, "/nix/store/i3ibgfskl99qd8rslafbpaa1dmxdzh1z-glibc-2.40-66/lib/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/16hvpw4b3r05girazh4rnwbw0jgjkb4l-xgcc-14.3.0-libgcc/lib/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/gs785h7im3vchbdxalrrjnmcan4dsign-julia-bin-1.11.6/lib/julia/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3

so I think we can likely merge this as-is.

LD_LIBRARY_PATH will work as a workaround if the Nix folks need it, and we can always revise this later to better support Nix if needed (it's no regression in functionality in any case)

@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch 4 times, most recently from 400adca to 47f1667 Compare December 1, 2025 16:21
**/
const char *jl_loader_probe_system_library(const char *libname, const char *symbol)
{
char buf[PATH_MAX];
Copy link
Member

Choose a reason for hiding this comment

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

PATH_MAX is much smaller than the maximum path length

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true, but exceeding PATH_MAX usually requires iterating path parts through openat etc. doesn't it?

I didn't think you could avoid ENAMETOOLONG if you try to open() a too-long string

Copy link
Member

Choose a reason for hiding this comment

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

On some OS, it may be the variable {PATH_MAX} on some systems not the constant PATH_MAX (though on linux I suppose it is constant, and long enough): https://pubs.opengroup.org/onlinepubs/009696599/basedefs/limits.h.html, pathconf

@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch 3 times, most recently from f8ce0da to c23c90d Compare December 1, 2025 17:13
@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch 2 times, most recently from b8e88e7 to 0d4bbc5 Compare December 2, 2025 14:48
Rather than relying on the linker to do all of the heavy lifting, this
changes our probing technique to directly parse the `ld.so.cache` and
`libstdc++.so.6` files. As long as we can expect `ld.so.cache` to be
available in `/etc` on all systems, this seems to be a reliable way to
locate system libraries on Linux systems.

That allows us to avoid `fork()`. For a small application that has just
started up `fork()` is no big deal, but it's quite heavy-handed for Julia-
as-a-library scenarios where resident memory may already be large.

Many soft-embedded targets also do not support fork() well, so it is
good for our compatibility to adjust this.
@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch from 0d4bbc5 to 6d1477f Compare December 2, 2025 15:14
@topolarity topolarity requested review from vtjnash and xal-0 December 2, 2025 16:24
@topolarity topolarity force-pushed the ct/forkless-libstdcxx-probe branch from 6d1477f to ea16b85 Compare December 2, 2025 17:40
@xal-0
Copy link
Member

xal-0 commented Dec 2, 2025

Works for me on Debian 8 now. 👍

Here's the test rig I have been using when loading JuliaC libraries into old libstdc++ programs: https://gist.github.com/xal-0/12a702f0c0e48848a33561b757107ec3

(localhost/juliaci-rootfs is our BinaryBuilder rootfs: docker import https://github.com/JuliaCI/rootfs-images/releases/download/v6.00/package_linux.x86_64.tar.gz juliaci-rootfs)

I have yet to try compiling a newer version of libstdc++ for Debian 8 and having Julia probe that, but will do that soon.

Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

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

SGTM

@topolarity topolarity added the merge me PR is reviewed. Merge when all tests are passing label Dec 2, 2025
@topolarity topolarity merged commit ac4ee59 into JuliaLang:master Dec 3, 2025
9 checks passed
@topolarity topolarity removed the merge me PR is reviewed. Merge when all tests are passing label Dec 3, 2025
KristofferC pushed a commit that referenced this pull request Dec 4, 2025
Somewhat of a companion to
#60248.

For a small application that has just started up `fork()` is not a huge
concern, but it's quite heavy-handed for Julia- as-a-library scenarios
where resident memory may already be large. Many soft-embedded targets
also do not support fork() well, so it is good for our compatibility to
adjust this.

Rather than relying on the linker to do all of the heavy lifting, this
changes our `libstdcxx` probe sequence to directly parse the
`ld.so.cache` and `libstdc++.so.6` files. As long as we can expect
`/etc/ld.so.cache` to be the same path on all Linux systems, this seems
to be a reliable way to locate system libraries.

(cherry picked from commit ac4ee59)
KristofferC pushed a commit that referenced this pull request Dec 4, 2025
Somewhat of a companion to
#60248.

For a small application that has just started up `fork()` is not a huge
concern, but it's quite heavy-handed for Julia- as-a-library scenarios
where resident memory may already be large. Many soft-embedded targets
also do not support fork() well, so it is good for our compatibility to
adjust this.

Rather than relying on the linker to do all of the heavy lifting, this
changes our `libstdcxx` probe sequence to directly parse the
`ld.so.cache` and `libstdc++.so.6` files. As long as we can expect
`/etc/ld.so.cache` to be the same path on all Linux systems, this seems
to be a reliable way to locate system libraries.

(cherry picked from commit ac4ee59)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants