Skip to content

libutil-tests: Skip leakedFDsAreClosed without close_range on musl - #16568

Merged
xokdvium merged 1 commit into
NixOS:masterfrom
philiptaron:worktree-issue-16520
Oct 8, 2026
Merged

xokdvium merged 1 commit into
NixOS:masterfrom
philiptaron:worktree-issue-16520

Conversation

@philiptaron

@philiptaron philiptaron commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

nix-util-tests-run-without-new-syscalls fails on every musl build, including nix-everything-static:

[  FAILED  ] runProgram2.leakedFDsAreClosed

That test run uses enosys to block close_range, among other syscalls, so the fallback paths get exercised. musl has no closefrom(), so doExecChild() closes leaked descriptors only through close_range. That's deliberately best-effort, so under enosys the descriptors stay open and the test fails. leakedFDsAreClosed (#16250) landed a day after close_range was added to the enosys run (#16247), and this combination has failed since then.

Context

Closes: #16520 (the leakedFDsAreClosed part; the ParseURL failures in the original report were a boost regression and no longer reproduce with the current nixpkgs pin).

As discussed in the review of a previous version of this PR, we skip the test instead of adding a /proc/self/fd fallback to doExecChild(). On a non-glibc Linux libc, the test now probes close_range and calls GTEST_SKIP() if it returns ENOSYS. glibc’s closefrom() has its own procfs fallback, so the test still runs under enosys there.

Testing

On x86_64-linux:

Build Result
.#nix-util-tests-static.tests.run-without-new-syscalls on master (5ca019f) fails: runProgram2.leakedFDsAreClosed
.#nix-util-tests-static.tests.run-without-new-syscalls with this change 819/819 pass
.#nix-util-tests-static.tests.run with this change 819/819 pass
.#nix-everything-static with this change builds; store/expr/fetchers/flake/util unit tests all pass

Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@philiptaron
philiptaron requested a review from edolstra as a code owner October 7, 2026 01:00
@philiptaron
philiptaron requested review from xokdvium and removed request for edolstra October 7, 2026 01:00
Comment thread src/libutil/linux/processes.cc Outdated
Comment on lines +90 to +94
long n = ::syscall(SYS_getdents64, dirFd, buf, sizeof(buf));
if (n <= 0) {
ok = n == 0;
break;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this actually necessary? readdir in musl seems like they would be perfectly fine to use here tbh.

@xokdvium

xokdvium commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Can we just disable the fallback tests when we don't have close_range? This closing is already best-effort tbh and I'm not sure we should be bending over backwards to support musl and ancient kernels. For most of nix's existence runProgram2 didn't close fds so while using glibc's fallback is nice because it's readily available, it seems like maybe we shouldn't bother overcomplicating this pile of complex code.

@xokdvium

xokdvium commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

If /proc can't be read, close everything below RLIMIT_NOFILE.

Is this an actual concern? I have previously did some fallbacks but now I'm doubting how useful that would be considering that some things are just impossible to do without /proc/self/fd still...

@philiptaron
philiptaron force-pushed the worktree-issue-16520 branch from 8a54750 to 0bdfc90 Compare October 7, 2026 22:51
@philiptaron philiptaron changed the title libutil/linux/processes: Close leaked FDs without close_range on musl libutil-tests: Skip leakedFDsAreClosed without close_range on musl Oct 7, 2026
musl has no closefrom(), so doExecChild() closes leaked descriptors only
via close_range, which is deliberately best-effort. The
`run-without-new-syscalls` test run blocks close_range with `enosys`, so
`runProgram2.leakedFDsAreClosed` has failed there on every musl build,
including `nix-everything-static`, since it was added.

Skip the test when close_range returns ENOSYS on a non-glibc Linux libc.
glibc's closefrom() has its own /proc/self/fd fallback, so the test
still runs under `enosys` there.

Fixes NixOS#16520 (the leakedFDsAreClosed part).
@philiptaron
philiptaron force-pushed the worktree-issue-16520 branch from 0bdfc90 to 3aacdcc Compare October 7, 2026 22:55
@philiptaron

Copy link
Copy Markdown
Contributor Author

Can we just disable the fallback tests when we don't have close_range?

Yeah, that's the better path. Did that instead of this code.

@philiptaron philiptaron closed this Oct 7, 2026
@philiptaron philiptaron reopened this Oct 7, 2026
@xokdvium
xokdvium added this pull request to the merge queue Oct 8, 2026
Merged via the queue into NixOS:master with commit 81da930 Oct 8, 2026
24 of 40 checks passed
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.

nix-util-tests-run tests failing

2 participants